From patchwork Thu Mar 19 15:10:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447465 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B60DA6CA for ; Thu, 19 Mar 2020 15:10:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9150920BED for ; Thu, 19 Mar 2020 15:10:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JyD0Snx9" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727327AbgCSPKh (ORCPT ); Thu, 19 Mar 2020 11:10:37 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:44272 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726871AbgCSPKg (ORCPT ); Thu, 19 Mar 2020 11:10:36 -0400 Received: by mail-wr1-f66.google.com with SMTP id o12so2940864wrh.11 for ; Thu, 19 Mar 2020 08:10:35 -0700 (PDT) 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=LxZjALu8+JdM1LNMX2SUCsKVBqP/y1yL79+aF6PkR+s=; b=JyD0Snx9IXb2NLcZnN4uGj42Qo/xJRV9BkgrIc9VfFNramHwlDvYDCwIYrIJOLjSte kcAKrgbnguxduU5EOXzBvUDnFDe5zeE0JEDS0uY54urAXhRXG/tGEQEmgDZbkTxra9aY hol8qLYZHU0jRf7ni7jR3C3QBVsoT72qty5e8GBRo+Pjt8m/YBkEvL9nMxH1OcwFMZEc sHQOqLYb0IPxvgJUoIbuQJMePB6q/4Sr7GFqRxH2SJn3AjgkQIWdHn+u2cShko/Kuh0L dTJXw+Vwqkk82sC1zIw+NCC3Etm5NebLPyP+cnfgqaYOrhaweNaItznydtSCLiA1jz4T M1+A== 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=LxZjALu8+JdM1LNMX2SUCsKVBqP/y1yL79+aF6PkR+s=; b=RdAk4KH74jz+GRI53WcgDGgfrp6maZ4PJFcMOezrNkCeyftBfM+jbZdTC65K9KregC OnqIB9wHcMrG6Q5uUtbX+5RW3UE/XE4l2Wfqk1XDuCm821kLnDuEWmuirLdXLzHD9dg2 HxqMaMmQiopIqTJhbBSo4jxjGUA7Jz9yM664/+mu+SDkLcfh/5S/jAKTh8g2cNyFM/Ia nHGm4TywEMmMk3CbTqbrJzLBqJ/Fzde4+VUlR94U6mT3+JdhtJy1UXqM1iENGo72mA9m kjSjqDI19X1AgMrOv7//20VLJGtqpByrE8vePSqlWwv8yg6mQ4UjhQjv73v39A5TXyx9 Onmg== X-Gm-Message-State: ANhLgQ2sxFgZX/xId/ICCUAD1i9QbiNweOGOYRxBfS9iHBMJajvHRsHL RJLdxF9U+1uc9QmrtWYTmgR4OFkt X-Google-Smtp-Source: ADFU+vuDHuUoikmY5Gr7o1HJyRaU9kwYkUmRc3X73092JQrFbi28nPB6UyPTDH+i21FjoyyRtYVr1g== X-Received: by 2002:a5d:56cd:: with SMTP id m13mr4756064wrw.236.1584630635262; Thu, 19 Mar 2020 08:10:35 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:34 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 01/14] fsnotify: tidy up FS_ and FAN_ constants Date: Thu, 19 Mar 2020 17:10:09 +0200 Message-Id: <20200319151022.31456-2-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Order by value, so the free value ranges are easier to find. Signed-off-by: Amir Goldstein --- include/linux/fsnotify_backend.h | 11 +++++------ include/uapi/linux/fanotify.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 1915bdba2fad..db3cabb4600e 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -49,16 +49,15 @@ #define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */ #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ -#define FS_ISDIR 0x40000000 /* event occurred against dir */ -#define FS_IN_ONESHOT 0x80000000 /* only send event once */ - -#define FS_DN_RENAME 0x10000000 /* file renamed */ -#define FS_DN_MULTISHOT 0x20000000 /* dnotify multishot */ - /* This inode cares about things that happen to its children. Always set for * dnotify and inotify. */ #define FS_EVENT_ON_CHILD 0x08000000 +#define FS_DN_RENAME 0x10000000 /* file renamed */ +#define FS_DN_MULTISHOT 0x20000000 /* dnotify multishot */ +#define FS_ISDIR 0x40000000 /* event occurred against dir */ +#define FS_IN_ONESHOT 0x80000000 /* only send event once */ + #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) /* diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index b9effa6f8503..2a1844edda47 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h @@ -25,9 +25,9 @@ #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ #define FAN_OPEN_EXEC_PERM 0x00040000 /* File open/exec in perm check */ -#define FAN_ONDIR 0x40000000 /* event occurred against dir */ +#define FAN_EVENT_ON_CHILD 0x08000000 /* Interested in child events */ -#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ +#define FAN_ONDIR 0x40000000 /* Event occurred against dir */ /* helper events */ #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ From patchwork Thu Mar 19 15:10:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447467 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 727BD913 for ; Thu, 19 Mar 2020 15:10:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 47CD020BED for ; Thu, 19 Mar 2020 15:10:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jkN0da8Z" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727456AbgCSPKl (ORCPT ); Thu, 19 Mar 2020 11:10:41 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:34876 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727416AbgCSPKl (ORCPT ); Thu, 19 Mar 2020 11:10:41 -0400 Received: by mail-wm1-f65.google.com with SMTP id m3so2715302wmi.0 for ; Thu, 19 Mar 2020 08:10:39 -0700 (PDT) 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=Q7txMGAZZZvw/5HVd0tg08nWoxYsIQi8ZzJMOkyog8c=; b=jkN0da8ZaBoRBkE8IZ2CXGEJQY9OwqyIyjJSBDXqmPwSLeFn5ljBmS9VaFma6EkOXl bO0+EApb2CA2DnoOyb1sRkiTK9ZXUnd2viw6SnZwZrGo21nOgwq4lpK6A3BohCPqDDTQ Ei8PojTUxas5B+eq5JHwRmYGU3inpjtbtTE8dyY9ZXp0J/47NcWTNmYwbCvmA4QhKF9P fZUrxgSyqBUVGrqisbWsgz9UqzzAFOv8E2Ro3+0ewPZQw1cm6Jp7aPlpBwq7AX+NWP5c Np8ONnvlReTB3TJhbxNmFHAJ2Ll5LHASp8IA7fq4gafrbmYDeZUPzn+FcJC9A0pH9cI1 4YTg== 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=Q7txMGAZZZvw/5HVd0tg08nWoxYsIQi8ZzJMOkyog8c=; b=PNnAMyuTLL0oXlr8byilGb/fBPJ5COF4LVnuyEuhnr9vxwhXdEKoP0gwlVx7in1Lev ujrrXAt+yK8kdJarSVGPpNlRHnaT7jaa9fiGb+eMB+gABwNHNQkcG84O5yLdeypviYx4 /T012xuGbzdW+QZvUCxfLi1tzcvmvVXFLNBQ1BKuYP7/mrYp0YG5TQshL4s3dNfdGiCF VnA25O2FxhXcSkNq8rNn0hl2S4TYHfRqpmLCbONKoBIgtovx9aqx2dfTuDyiEbvUcJN6 VOE6ATCPnWLtqyDo5VAKi9SzhbFmCEnMH8f3MrDbJSk1NXTGuo1P3/kvXOl5TBcwG3Fy gpOA== X-Gm-Message-State: ANhLgQ3IDPIqtvBerHUAa9xgq5NOT7RlKuJMnzN1g19DDemcdZ2iFqTE +a+c8oPvinlnloonaPwSAMHBRvDy X-Google-Smtp-Source: ADFU+vsCa//1uAFz6oOxDe1foZnIaO3vRqDsqtIKVOcsb24o5H95uoQGVuikFq7mMdV7x/3gb3X57g== X-Received: by 2002:a7b:c458:: with SMTP id l24mr4212194wmi.120.1584630639118; Thu, 19 Mar 2020 08:10:39 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:38 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 02/14] fsnotify: factor helpers fsnotify_dentry() and fsnotify_file() Date: Thu, 19 Mar 2020 17:10:10 +0200 Message-Id: <20200319151022.31456-3-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Most of the code in fsnotify hooks is boiler plate of one or the other. Signed-off-by: Amir Goldstein --- include/linux/fsnotify.h | 99 +++++++++++++++------------------------- 1 file changed, 37 insertions(+), 62 deletions(-) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index a2d5d175d3c1..f54936aa0365 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -41,16 +41,36 @@ static inline int fsnotify_parent(const struct path *path, } /* - * Simple wrapper to consolidate calls fsnotify_parent()/fsnotify() when - * an event is on a path. + * Simple wrappers to consolidate calls fsnotify_parent()/fsnotify() when + * an event is on a file/dentry. */ -static inline int fsnotify_path(struct inode *inode, const struct path *path, - __u32 mask) +static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask) { - int ret = fsnotify_parent(path, NULL, mask); + struct inode *inode = d_inode(dentry); + if (S_ISDIR(inode->i_mode)) + mask |= FS_ISDIR; + + fsnotify_parent(NULL, dentry, mask); + fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); +} + +static inline int fsnotify_file(struct file *file, __u32 mask) +{ + const struct path *path = &file->f_path; + struct inode *inode = file_inode(file); + int ret; + + if (file->f_mode & FMODE_NONOTIFY) + return 0; + + if (S_ISDIR(inode->i_mode)) + mask |= FS_ISDIR; + + ret = fsnotify_parent(path, NULL, mask); if (ret) return ret; + return fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); } @@ -58,19 +78,16 @@ static inline int fsnotify_path(struct inode *inode, const struct path *path, static inline int fsnotify_perm(struct file *file, int mask) { int ret; - const struct path *path = &file->f_path; - struct inode *inode = file_inode(file); __u32 fsnotify_mask = 0; - if (file->f_mode & FMODE_NONOTIFY) - return 0; if (!(mask & (MAY_READ | MAY_OPEN))) return 0; + if (mask & MAY_OPEN) { fsnotify_mask = FS_OPEN_PERM; if (file->f_flags & __FMODE_EXEC) { - ret = fsnotify_path(inode, path, FS_OPEN_EXEC_PERM); + ret = fsnotify_file(file, FS_OPEN_EXEC_PERM); if (ret) return ret; @@ -79,10 +96,7 @@ static inline int fsnotify_perm(struct file *file, int mask) fsnotify_mask = FS_ACCESS_PERM; } - if (S_ISDIR(inode->i_mode)) - fsnotify_mask |= FS_ISDIR; - - return fsnotify_path(inode, path, fsnotify_mask); + return fsnotify_file(file, fsnotify_mask); } /* @@ -229,15 +243,7 @@ static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry) */ static inline void fsnotify_access(struct file *file) { - const struct path *path = &file->f_path; - struct inode *inode = file_inode(file); - __u32 mask = FS_ACCESS; - - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - if (!(file->f_mode & FMODE_NONOTIFY)) - fsnotify_path(inode, path, mask); + fsnotify_file(file, FS_ACCESS); } /* @@ -245,15 +251,7 @@ static inline void fsnotify_access(struct file *file) */ static inline void fsnotify_modify(struct file *file) { - const struct path *path = &file->f_path; - struct inode *inode = file_inode(file); - __u32 mask = FS_MODIFY; - - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - if (!(file->f_mode & FMODE_NONOTIFY)) - fsnotify_path(inode, path, mask); + fsnotify_file(file, FS_MODIFY); } /* @@ -261,16 +259,12 @@ static inline void fsnotify_modify(struct file *file) */ static inline void fsnotify_open(struct file *file) { - const struct path *path = &file->f_path; - struct inode *inode = file_inode(file); __u32 mask = FS_OPEN; - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; if (file->f_flags & __FMODE_EXEC) mask |= FS_OPEN_EXEC; - fsnotify_path(inode, path, mask); + fsnotify_file(file, mask); } /* @@ -278,16 +272,10 @@ static inline void fsnotify_open(struct file *file) */ static inline void fsnotify_close(struct file *file) { - const struct path *path = &file->f_path; - struct inode *inode = file_inode(file); - fmode_t mode = file->f_mode; - __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; + __u32 mask = (file->f_mode & FMODE_WRITE) ? FS_CLOSE_WRITE : + FS_CLOSE_NOWRITE; - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - if (!(file->f_mode & FMODE_NONOTIFY)) - fsnotify_path(inode, path, mask); + fsnotify_file(file, mask); } /* @@ -295,14 +283,7 @@ static inline void fsnotify_close(struct file *file) */ static inline void fsnotify_xattr(struct dentry *dentry) { - struct inode *inode = dentry->d_inode; - __u32 mask = FS_ATTRIB; - - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - fsnotify_parent(NULL, dentry, mask); - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); + fsnotify_dentry(dentry, FS_ATTRIB); } /* @@ -311,7 +292,6 @@ static inline void fsnotify_xattr(struct dentry *dentry) */ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) { - struct inode *inode = dentry->d_inode; __u32 mask = 0; if (ia_valid & ATTR_UID) @@ -332,13 +312,8 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) if (ia_valid & ATTR_MODE) mask |= FS_ATTRIB; - if (mask) { - if (S_ISDIR(inode->i_mode)) - mask |= FS_ISDIR; - - fsnotify_parent(NULL, dentry, mask); - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); - } + if (mask) + fsnotify_dentry(dentry, mask); } #endif /* _LINUX_FS_NOTIFY_H */ From patchwork Thu Mar 19 15:10:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447469 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 585B0913 for ; Thu, 19 Mar 2020 15:10:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 371CF20B1F for ; Thu, 19 Mar 2020 15:10:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="H8Mzl5Qe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727488AbgCSPKn (ORCPT ); Thu, 19 Mar 2020 11:10:43 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:54341 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726912AbgCSPKn (ORCPT ); Thu, 19 Mar 2020 11:10:43 -0400 Received: by mail-wm1-f68.google.com with SMTP id f130so1647324wmf.4 for ; Thu, 19 Mar 2020 08:10:41 -0700 (PDT) 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=ykQtzazlMMXyRropYxwlMaMqcnSkmw7/TA8y9MsBDPQ=; b=H8Mzl5Qe5Le74UGPXY64glF89/3Gli//nV9RmtppQkOU87kbP+HDQNppmW06svzfgm sJXqVsvkVxLY4aGczePo9eWOGNsJYl2H4KoghQEF28MyP1AemTcplKnn9YGzqIk0P47L a4ITwx5Dbl0Eh9HATOdJqY+Ip8DUVuJIHSoFDt3fZ8Av9ud8d+ftACI8MbxClcqyv94y TchMfaP9HQIEjVZS7CnhHNkQdSDwBOk3TP6mBnua4nA5FlaerIp3sT01Zf81GjERfJOL 4w6/lbYpqKTILtOh2N4cJTONFb4Gt1ZpkOGVB71DDPBRkkRwY469f6G6B4l5MY2XZ0gb /4kQ== 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=ykQtzazlMMXyRropYxwlMaMqcnSkmw7/TA8y9MsBDPQ=; b=CrS9+ZhBKPYIA0iRVoTwliUjrQUfERkNV+E5p1PErVhlL4K843ymp99fMnLY9cQhfZ tZcfh9oJZ2TYGaBEaMU4x8oI7h2sg5XVaeEh3juIoaCIB9O95mz7MILi8I/257fyh4Lh jv7wZkSa9RUMbZ8DSmLOv6pXRj8EJeGFwtq2d2DSsZ7dJK/dmUgb17OZbublNF1+eEsf fYNVggivQmmsq2/j+CrT0BrDmqVWDUKVquXBtytpBQ0gqCbzrZJkWa8C8/YfKEuUOme7 43h/PwQPcfqbMEBDnqXiR7iW19quHqZRqQjxSkfiAm/mgoHNeeSSggycmws9YumX77UT rO8w== X-Gm-Message-State: ANhLgQ2gATbZV+stwDkJm7S8fQDZ2GYY8QAHbP+h6SwGqyaGhVRxYrtt J5vZC3YMIY/nTXRPBVH08lE= X-Google-Smtp-Source: ADFU+vv0j+hqyQpU7zGIRpYieaP77GTWV1Zp8Owjlb3ukmz51rbNu/FCMVEUp4RtCIMiDmHJP1rhDw== X-Received: by 2002:a05:600c:21d1:: with SMTP id x17mr4192618wmj.94.1584630640468; Thu, 19 Mar 2020 08:10:40 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:39 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 03/14] fsnotify: funnel all dirent events through fsnotify_name() Date: Thu, 19 Mar 2020 17:10:11 +0200 Message-Id: <20200319151022.31456-4-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Factor out fsnotify_name() from fsnotify_dirent(), so it can also serve link and rename events and use this helper to report all directory entry change events. Both helpers return void because no caller checks their return value. Signed-off-by: Amir Goldstein --- include/linux/fsnotify.h | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index f54936aa0365..751da17e003d 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -18,16 +18,24 @@ #include /* - * Notify this @dir inode about a change in the directory entry @dentry. + * Notify this @dir inode about a change in a child directory entry. + * The directory entry may have turned positive or negative or its inode may + * have changed (i.e. renamed over). * * Unlike fsnotify_parent(), the event will be reported regardless of the * FS_EVENT_ON_CHILD mask on the parent inode. */ -static inline int fsnotify_dirent(struct inode *dir, struct dentry *dentry, - __u32 mask) +static inline void fsnotify_name(struct inode *dir, __u32 mask, + struct inode *child, + const struct qstr *name, u32 cookie) { - return fsnotify(dir, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE, - &dentry->d_name, 0); + fsnotify(dir, mask, child, FSNOTIFY_EVENT_INODE, name, cookie); +} + +static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, + __u32 mask) +{ + fsnotify_name(dir, mask, d_inode(dentry), &dentry->d_name, 0); } /* Notify this dentry's parent about a child's events. */ @@ -136,10 +144,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, mask |= FS_ISDIR; } - fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name, - fs_cookie); - fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name, - fs_cookie); + fsnotify_name(old_dir, old_dir_mask, source, old_name, fs_cookie); + fsnotify_name(new_dir, new_dir_mask, source, new_name, fs_cookie); if (target) fsnotify_link_count(target); @@ -194,12 +200,13 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) * Note: We have to pass also the linked inode ptr as some filesystems leave * new_dentry->d_inode NULL and instantiate inode pointer later */ -static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) +static inline void fsnotify_link(struct inode *dir, struct inode *inode, + struct dentry *new_dentry) { fsnotify_link_count(inode); audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE); - fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, &new_dentry->d_name, 0); + fsnotify_name(dir, FS_CREATE, inode, &new_dentry->d_name, 0); } /* From patchwork Thu Mar 19 15:10:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447471 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 896E16CA for ; Thu, 19 Mar 2020 15:10:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5C3FB20BED for ; Thu, 19 Mar 2020 15:10:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DwNdAsPk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727705AbgCSPKq (ORCPT ); Thu, 19 Mar 2020 11:10:46 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:33332 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727470AbgCSPKo (ORCPT ); Thu, 19 Mar 2020 11:10:44 -0400 Received: by mail-wm1-f65.google.com with SMTP id r7so5012757wmg.0 for ; Thu, 19 Mar 2020 08:10:42 -0700 (PDT) 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=n4QRMUmDbTzXCoJUleJyV2gfRI6X6+6qFC3WMs48hTs=; b=DwNdAsPkiPunzbj+ywhrS3uKXyHycVSL4z06jmdPC9jXe5xmomn8wcRGkcuXLbTFeo r9p0TTNQkrumuGrMfjWecznRD84OdJxZ05YHwuxonel08cKeuYKhErS+ipUlue4CXpM4 9ssKzK/uD4ihq4LoGv9QhvgskK1QIRRV7uytJCTvUWOA9rg5isCFCuFRU8Bwy0FdkFwh MZZiGSbm679OLSIEPrTXO+60MqBVkmOgT+A7PZafEO9m278QDPTPDAjrcl8Ifib5R/Q+ LstUuVT/kY7E0mIgVkHoEPmgs1BdyqkWFIHP98LAKYwzFITmZ2kv5WkoN4zinGr9lq+M 3sLQ== 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=n4QRMUmDbTzXCoJUleJyV2gfRI6X6+6qFC3WMs48hTs=; b=sfCAPyTu322bGFycOFfhNJnX7sGKxpNjhQBPNJPJEoQ257o9AHMBspzb2jJGJrd82L 5FsPEGW6U6BGczrlQ+XMBjPE0i04UrO0U4vsWh7+w3141aO7RTQ3wrKZXS3uy7TKS2Ig tKo/B9ag31CBFJ+BN+WAWkIdRaqUdJylR/AIKaoNeKhhenwtZ+a87dGWPf5h9qixaNZz xTP1u6xZ6T13HM6fMP7TR0V/UFHGIrSvVMeU54T7PAkCKH9LjFeotXaZ2jYKaoUUrvT2 xlj3H2zyx/vdSlnONyEM+pbn7GTICHWBzuXo5WklWI8++Fpy1mTsI0RRlfD6N7GSh24C 6L0w== X-Gm-Message-State: ANhLgQ1eB6lHwGDX1HhUdEojvtg7eHH9EGvfVwh9s10VOVGVRbYHKTsd hBkutNsbBU61La6cTyzPCxQ= X-Google-Smtp-Source: ADFU+vtokGSPaLXd74+WAAM0zeuWv8x3WqES9wBTHe1OrtpdTqZPi5WrMviNoKy1+2Cc4uWXPRzygA== X-Received: by 2002:a1c:5684:: with SMTP id k126mr4369773wmb.181.1584630642269; Thu, 19 Mar 2020 08:10:42 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:41 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 04/14] fsnotify: use helpers to access data by data_type Date: Thu, 19 Mar 2020 17:10:12 +0200 Message-Id: <20200319151022.31456-5-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Create helpers to access path and inode from different data types. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 18 +++++++-------- fs/notify/fsnotify.c | 5 ++-- fs/notify/inotify/inotify_fsnotify.c | 8 +++---- include/linux/fsnotify_backend.h | 34 ++++++++++++++++++++++++---- kernel/audit_fsnotify.c | 13 ++--------- kernel/audit_watch.c | 16 ++----------- 6 files changed, 48 insertions(+), 46 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 5778d1347b35..19ec7a4f4d50 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -151,7 +151,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, { __u32 marks_mask = 0, marks_ignored_mask = 0; __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS; - const struct path *path = data; + const struct path *path = fsnotify_data_path(data, data_type); struct fsnotify_mark *mark; int type; @@ -160,7 +160,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { /* Do we have path to open a file descriptor? */ - if (data_type != FSNOTIFY_EVENT_PATH) + if (!path) return 0; /* Path type events are only relevant for files and dirs */ if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry)) @@ -269,11 +269,8 @@ static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask, { 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; + + return (struct inode *)fsnotify_data_inode(data, data_type); } struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, @@ -284,6 +281,7 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, struct fanotify_event *event = NULL; gfp_t gfp = GFP_KERNEL_ACCOUNT; struct inode *id = fanotify_fid_inode(inode, mask, data, data_type); + const struct path *path = fsnotify_data_path(data, data_type); /* * For queues with unlimited length lost events are not expected and @@ -324,10 +322,10 @@ init: __maybe_unused 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, id, gfp, fsid); - } else if (data_type == FSNOTIFY_EVENT_PATH) { + } else if (path) { event->fh_type = FILEID_ROOT; - event->path = *((struct path *)data); - path_get(&event->path); + event->path = *path; + path_get(path); } else { event->fh_type = FILEID_INVALID; event->path.mnt = NULL; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 46f225580009..a5d6467f89a0 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -318,6 +318,7 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, const struct qstr *file_name, u32 cookie) { + const struct path *path = fsnotify_data_path(data, data_is); struct fsnotify_iter_info iter_info = {}; struct super_block *sb = to_tell->i_sb; struct mount *mnt = NULL; @@ -325,8 +326,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, int ret = 0; __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS); - if (data_is == FSNOTIFY_EVENT_PATH) { - mnt = real_mount(((const struct path *)data)->mnt); + if (path) { + mnt = real_mount(path->mnt); mnt_or_sb_mask |= mnt->mnt_fsnotify_mask; } /* An event "on child" is not intended for a mount/sb mark */ diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index d510223d302c..6bb98522bbfd 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -61,6 +61,7 @@ int inotify_handle_event(struct fsnotify_group *group, const struct qstr *file_name, u32 cookie, struct fsnotify_iter_info *iter_info) { + const struct path *path = fsnotify_data_path(data, data_type); struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); struct inotify_inode_mark *i_mark; struct inotify_event_info *event; @@ -73,12 +74,9 @@ int inotify_handle_event(struct fsnotify_group *group, return 0; if ((inode_mark->mask & FS_EXCL_UNLINK) && - (data_type == FSNOTIFY_EVENT_PATH)) { - const struct path *path = data; + path && d_unlinked(path->dentry)) + return 0; - if (d_unlinked(path->dentry)) - return 0; - } if (file_name) { len = file_name->len; alloc_len += len + 1; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index db3cabb4600e..5cc838db422a 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -212,10 +212,36 @@ struct fsnotify_group { }; }; -/* when calling fsnotify tell it if the data is a path or inode */ -#define FSNOTIFY_EVENT_NONE 0 -#define FSNOTIFY_EVENT_PATH 1 -#define FSNOTIFY_EVENT_INODE 2 +/* When calling fsnotify tell it if the data is a path or inode */ +enum fsnotify_data_type { + FSNOTIFY_EVENT_NONE, + FSNOTIFY_EVENT_PATH, + FSNOTIFY_EVENT_INODE, +}; + +static inline const struct inode *fsnotify_data_inode(const void *data, + int data_type) +{ + switch (data_type) { + case FSNOTIFY_EVENT_INODE: + return data; + case FSNOTIFY_EVENT_PATH: + return d_inode(((const struct path *)data)->dentry); + default: + return NULL; + } +} + +static inline const struct path *fsnotify_data_path(const void *data, + int data_type) +{ + switch (data_type) { + case FSNOTIFY_EVENT_PATH: + return data; + default: + return NULL; + } +} enum fsnotify_obj_type { FSNOTIFY_OBJ_TYPE_INODE, diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index f0d243318452..3596448bfdab 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c @@ -160,23 +160,14 @@ static int audit_mark_handle_event(struct fsnotify_group *group, { struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); struct audit_fsnotify_mark *audit_mark; - const struct inode *inode = NULL; + const struct inode *inode = fsnotify_data_inode(data, data_type); audit_mark = container_of(inode_mark, struct audit_fsnotify_mark, mark); BUG_ON(group != audit_fsnotify_group); - switch (data_type) { - case (FSNOTIFY_EVENT_PATH): - inode = ((const struct path *)data)->dentry->d_inode; - break; - case (FSNOTIFY_EVENT_INODE): - inode = (const struct inode *)data; - break; - default: - BUG(); + if (WARN_ON(!inode)) return 0; - } if (mask & (FS_CREATE|FS_MOVED_TO|FS_DELETE|FS_MOVED_FROM)) { if (audit_compare_dname_path(dname, audit_mark->path, AUDIT_NAME_FULL)) diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 4508d5e0cf69..dcfbb44c6720 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -473,25 +473,13 @@ static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotify_iter_info *iter_info) { struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); - const struct inode *inode; + const struct inode *inode = fsnotify_data_inode(data, data_type); struct audit_parent *parent; parent = container_of(inode_mark, struct audit_parent, mark); BUG_ON(group != audit_watch_group); - - switch (data_type) { - case (FSNOTIFY_EVENT_PATH): - inode = d_backing_inode(((const struct path *)data)->dentry); - break; - case (FSNOTIFY_EVENT_INODE): - inode = (const struct inode *)data; - break; - default: - BUG(); - inode = NULL; - break; - } + WARN_ON(!inode); if (mask & (FS_CREATE|FS_MOVED_TO) && inode) audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0); From patchwork Thu Mar 19 15:10:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447477 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 82C436CA for ; Thu, 19 Mar 2020 15:10:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 62E7E20BED for ; Thu, 19 Mar 2020 15:10:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ncXdvxKe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727661AbgCSPKq (ORCPT ); Thu, 19 Mar 2020 11:10:46 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:33580 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727464AbgCSPKp (ORCPT ); Thu, 19 Mar 2020 11:10:45 -0400 Received: by mail-wr1-f65.google.com with SMTP id a25so3507084wrd.0 for ; Thu, 19 Mar 2020 08:10:44 -0700 (PDT) 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=/7jTCSsyzZWwp7yRyA/w3XAM2WGW6qSw6oXjdg2EIwQ=; b=ncXdvxKew51HtZWn9kntNCK9nGdh+R2FXx6ZOX7e7OwwEobe6rjJ8B0H/pBOE/W2WD eSJqg4WeVCc8cwNOwUVAY0fP+GVHX4tz4EE2sq67QDD65U/Jjq364LDihJh8126tHnYo prsu+VCWw7PrKRjZuhxFyW2DGpmrqu4MOezKAbq5x/fEn00AnKbrEO1REyxJbo0kNcYU fBf57g22YaPmxyKAomPxgxEfJt/+626OWHul+tEioaqJZFP3iPDpNlkD6a3ap87q2oMl 52kdQPTmu9kAe5xDvcoGeOjAp0SQCyzCyULm3JtWyJNew+3gXIy2BQJGpW6VGCL5SLHH MF5w== 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=/7jTCSsyzZWwp7yRyA/w3XAM2WGW6qSw6oXjdg2EIwQ=; b=OqCHUsLj0zeFiNj2OdoRYkvxT/f8rR+1sv07ZRyRnBcI37kmc7Tegry1U+SixMowgu wKNXrUgXlHxFzr1vns97BSPmgRGAoc/Ghz1eHi32WK1DCn7kjbQYEC4rSepQshSnndCZ 7jVHpWLuwUcotWY8/Y/skD3kf39qg9rN/brdUWsfFlluIcI2ibV02TzY6y4MKd/JSbYY PweSv4JKhSPA00qFSAkovyz8c0uNPPOtVu/S43w0l66b+fMwWIODRzHXHzxLUmj3f+jc 2RoD1rwWRjUQpmflZ7AS3a+Hkah5LbxZjwctuzJW5ms738r6fyX7C0BzM2WPZ98soZyP PugQ== X-Gm-Message-State: ANhLgQ1RxOuN0tk6ahbOHxlQS+P6S3dmLL9VPOaIJMFeC1YRUmtOu6Ub mEtzGh/PmD1JkWZV48LbToDLS8FF X-Google-Smtp-Source: ADFU+vsoKD179LvBz4+QCZEnnozAS3NWitgcD663gu3DCcWOfh7tuDY6grbY/KTFo5lFDd/OjKUQow== X-Received: by 2002:adf:dd8a:: with SMTP id x10mr5172762wrl.38.1584630643810; Thu, 19 Mar 2020 08:10:43 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:43 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 05/14] fsnotify: simplify arguments passing to fsnotify_parent() Date: Thu, 19 Mar 2020 17:10:13 +0200 Message-Id: <20200319151022.31456-6-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Instead of passing both dentry and path and having to figure out which one to use, pass data/data_type to simplify the code. Signed-off-by: Amir Goldstein --- fs/notify/fsnotify.c | 15 ++++----------- include/linux/fsnotify.h | 14 ++------------ include/linux/fsnotify_backend.h | 14 ++++++++------ 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index a5d6467f89a0..193530f57963 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -143,15 +143,13 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) } /* Notify this dentry's parent about a child's events. */ -int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask) +int fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, + int data_type) { struct dentry *parent; struct inode *p_inode; int ret = 0; - if (!dentry) - dentry = path->dentry; - if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) return 0; @@ -168,12 +166,7 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask mask |= FS_EVENT_ON_CHILD; take_dentry_name_snapshot(&name, dentry); - if (path) - ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, - &name.name, 0); - else - ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, - &name.name, 0); + ret = fsnotify(p_inode, mask, data, data_type, &name.name, 0); release_dentry_name_snapshot(&name); } @@ -181,7 +174,7 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask return ret; } -EXPORT_SYMBOL_GPL(__fsnotify_parent); +EXPORT_SYMBOL_GPL(fsnotify_parent); static int send_to_group(struct inode *to_tell, __u32 mask, const void *data, diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 751da17e003d..860018f3e545 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -38,16 +38,6 @@ static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, fsnotify_name(dir, mask, d_inode(dentry), &dentry->d_name, 0); } -/* Notify this dentry's parent about a child's events. */ -static inline int fsnotify_parent(const struct path *path, - struct dentry *dentry, __u32 mask) -{ - if (!dentry) - dentry = path->dentry; - - return __fsnotify_parent(path, dentry, mask); -} - /* * Simple wrappers to consolidate calls fsnotify_parent()/fsnotify() when * an event is on a file/dentry. @@ -59,7 +49,7 @@ static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask) if (S_ISDIR(inode->i_mode)) mask |= FS_ISDIR; - fsnotify_parent(NULL, dentry, mask); + fsnotify_parent(dentry, mask, inode, FSNOTIFY_EVENT_INODE); fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); } @@ -75,7 +65,7 @@ static inline int fsnotify_file(struct file *file, __u32 mask) if (S_ISDIR(inode->i_mode)) mask |= FS_ISDIR; - ret = fsnotify_parent(path, NULL, mask); + ret = fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH); if (ret) return ret; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 5cc838db422a..337c87cf34d6 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -376,9 +376,10 @@ struct fsnotify_mark { /* called from the vfs helpers */ /* main fsnotify call to send events */ -extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, - const struct qstr *name, u32 cookie); -extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask); +extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, + int data_type, const struct qstr *name, u32 cookie); +extern int fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, + int data_type); extern void __fsnotify_inode_delete(struct inode *inode); extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); extern void fsnotify_sb_delete(struct super_block *sb); @@ -533,13 +534,14 @@ static inline void fsnotify_init_event(struct fsnotify_event *event, #else -static inline int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, - const struct qstr *name, u32 cookie) +static inline int fsnotify(struct inode *to_tell, __u32 mask, const void *data, + int data_type, const struct qstr *name, u32 cookie) { return 0; } -static inline int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask) +static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, + const void *data, int data_type) { return 0; } From patchwork Thu Mar 19 15:10:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447473 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CBCCB6CA for ; Thu, 19 Mar 2020 15:10:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AA81D2072D for ; Thu, 19 Mar 2020 15:10:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="P5p1XcLD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727757AbgCSPKs (ORCPT ); Thu, 19 Mar 2020 11:10:48 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:38324 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726912AbgCSPKr (ORCPT ); Thu, 19 Mar 2020 11:10:47 -0400 Received: by mail-wm1-f65.google.com with SMTP id l20so2703300wmi.3 for ; Thu, 19 Mar 2020 08:10:46 -0700 (PDT) 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=qUL5AUxiOJ5bWL9Ipf/Y87tgOUiq0x7sxDlFXUm/tco=; b=P5p1XcLDBdF1FZxIcfnRf6nbRdYvTPW9x8zfWpK8fLI45DkgR8BAlXblz6LYhZwFLI RZAJHoXTKlgP+XHsmbFVnyccTDezBv1EYKk/CdEZgfstSktEgmpbP3S1d9w6SNseFtN8 Gl0EK7nn+CsmmEFIpI5zsQkp0vPR2IqxBoFI5wvRBpp8hjiMkX67oawG4tL2M8NA+11V c6Z83tCa6xvYGmO44k+Y8oNK1bpAjeRDgXH77dFKCQbte6EK2bDpH/rICDHcgrg1rU5g 1kKdXRUkyJdlUA3bBZ3maTFHOiO7MU/4lbsQEuazgINmGTyFxmJp3QSRWjvaAyvsTnbR SRYQ== 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=qUL5AUxiOJ5bWL9Ipf/Y87tgOUiq0x7sxDlFXUm/tco=; b=R/NtNPMPxzf4SXtc8cqUmFuShPxkyABdcDNEjxJPZ1kZhQoNfWQ9IXs7kjQqFgwBRI l5ZFmyTq+3lZ0U/53BQxGycS0TL+CvtVdBOoiqrpgHN5GgJsSqEAdwY2QbVXJmrzQNe8 lg8PWyR2a5nq1pKWTMbewznf0GsXzYx1RV4cDCkGWs5ddwmmvXsOBZCqCxm/MRhYdVb+ edSa++hSXQsFWey4D3cp9yh4OXA5YT9tHOFI6aE9PeG46fQjI7pFUStBPfS3jah6mXkX RBM2HQQFeq6FdWjVH0YKKPGl2Vp8uU8mSFZnGaSTsUpOK0Y79vVOMEI1o+ln6ruWVasD OlPg== X-Gm-Message-State: ANhLgQ3sZNpQo6AezM1XTZ3H3okyjK8n3Iru7z+3fBQng6MtqC4UK2iB jyKkcyee0cKC8NgBfLRTcnJvcOtQ X-Google-Smtp-Source: ADFU+vsNGPP1UgdLJ3XyPi4p24tjaTSfCa3Tv+aM1KDLqAay2zqt0OJVWJ/mJS53uG5qWk/bPjjuEQ== X-Received: by 2002:a1c:1d15:: with SMTP id d21mr4232561wmd.101.1584630645791; Thu, 19 Mar 2020 08:10:45 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:45 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 06/14] fsnotify: pass dentry instead of inode for events possible on child Date: Thu, 19 Mar 2020 17:10:14 +0200 Message-Id: <20200319151022.31456-7-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Most events that can be reported to watching parent pass FSNOTIFY_EVENT_PATH as event data, except for FS_ARRTIB and FS_MODIFY as a result of truncate. Define a new data type to pass for event - FSNOTIFY_EVENT_DENTRY and use it to pass the dentry instead of it's ->d_inode for those events. Soon, we are going to use the dentry data type to report events with name info in fanotify backend. Signed-off-by: Amir Goldstein --- include/linux/fsnotify.h | 4 ++-- include/linux/fsnotify_backend.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 860018f3e545..d286663fcef2 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -49,8 +49,8 @@ static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask) if (S_ISDIR(inode->i_mode)) mask |= FS_ISDIR; - fsnotify_parent(dentry, mask, inode, FSNOTIFY_EVENT_INODE); - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); + fsnotify_parent(dentry, mask, dentry, FSNOTIFY_EVENT_DENTRY); + fsnotify(inode, mask, dentry, FSNOTIFY_EVENT_DENTRY, NULL, 0); } static inline int fsnotify_file(struct file *file, __u32 mask) diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 337c87cf34d6..ab0913619403 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -217,6 +217,7 @@ enum fsnotify_data_type { FSNOTIFY_EVENT_NONE, FSNOTIFY_EVENT_PATH, FSNOTIFY_EVENT_INODE, + FSNOTIFY_EVENT_DENTRY, }; static inline const struct inode *fsnotify_data_inode(const void *data, @@ -225,6 +226,8 @@ static inline const struct inode *fsnotify_data_inode(const void *data, switch (data_type) { case FSNOTIFY_EVENT_INODE: return data; + case FSNOTIFY_EVENT_DENTRY: + return d_inode(data); case FSNOTIFY_EVENT_PATH: return d_inode(((const struct path *)data)->dentry); default: @@ -232,6 +235,20 @@ static inline const struct inode *fsnotify_data_inode(const void *data, } } +static inline struct dentry *fsnotify_data_dentry(const void *data, + int data_type) +{ + switch (data_type) { + case FSNOTIFY_EVENT_DENTRY: + /* Non const is needed for dget() */ + return (struct dentry *)data; + case FSNOTIFY_EVENT_PATH: + return ((const struct path *)data)->dentry; + default: + return NULL; + } +} + static inline const struct path *fsnotify_data_path(const void *data, int data_type) { From patchwork Thu Mar 19 15:10:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447475 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D5BEF913 for ; Thu, 19 Mar 2020 15:10:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B50C920CC7 for ; Thu, 19 Mar 2020 15:10:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MDB6HsD0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727793AbgCSPKu (ORCPT ); Thu, 19 Mar 2020 11:10:50 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:34914 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727346AbgCSPKt (ORCPT ); Thu, 19 Mar 2020 11:10:49 -0400 Received: by mail-wm1-f65.google.com with SMTP id m3so2715919wmi.0 for ; Thu, 19 Mar 2020 08:10:47 -0700 (PDT) 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=Z4GNpwenHqxdfK7tI9HPRZfTZgRQd8dQU+fYl2hE01U=; b=MDB6HsD0pJmPsysjqQCjiRc+aQQSOvqYfZ9MJ8E/xRwgG4Upkk8ASWTu5ZhIrcE5z8 Y/XiCEK/JYEwFdAczmLYyYp7dNGl7CxN2kukNkz36T+8NNhHLmGYVdCo8gEr4qd8hAbf hXfiaWaN3KIqvVPA0S2Hn4J+mJuXdJ0o98YorCazwxsB3emuHDItdEAyjOt7I9e/hQDe p5/2olRME7gDx/adIFbSlE8jeGmF7tlTO3xaRHGlHXrpcIIQ2qHs41MQOtlZkxkWuABe I8dxuMuAgDn1T1ZtdNv/LA8nJ16Qy1A+nKLJ4XCtgSiNjt8r0LX2kA8tDp0LGLD1kxAn otEw== 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=Z4GNpwenHqxdfK7tI9HPRZfTZgRQd8dQU+fYl2hE01U=; b=YOPgW3tF+l2AWQyljjB9xK5hWzILREhFW8yYiBF6EofIjVNFeMRVwFUg0o/9b7NyGV ua4EWkEYruqYPp2Pt6+NwBzJ7Jj9VMB+SIv2E06db+GOSJmqJujZb89CW7H2T/FlF9zW 50rcEyJUdeqYI/SfMYgJXg5RDBwsE4xtTIW+CkMDCpcMZ2Eea0LZGLOtHEuX4FZDq46V XLH3A9sEMNQR41K1b6LVsygM1PdACSCngrCkGmb4tzTmnvQlWx1f2yeuMk5TWQT9AP72 Ew7+2kO6Nggnq83Bc9e0bx/ya5xdmT5e5yTjgnrsX/QkYrZq26wbYAm8rxUanafgF7vi 3UxA== X-Gm-Message-State: ANhLgQ0DWIJKYD5Kxo6k3vetZxuX8cm8dv6yyfFFzlqkc1zpU+hSFs3Y yBe9ZqqCriTiOqjNgqcByaE= X-Google-Smtp-Source: ADFU+vv8yXy0U6jzpl9UN3gszOPBVIpkK3zP/Y91eIb/7GYCuAO6Q5a1xTkpetf1JOXLMYGPNxHjVw== X-Received: by 2002:a1c:23d5:: with SMTP id j204mr4463540wmj.59.1584630647113; Thu, 19 Mar 2020 08:10:47 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:46 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 07/14] fsnotify: replace inode pointer with an object id Date: Thu, 19 Mar 2020 17:10:15 +0200 Message-Id: <20200319151022.31456-8-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The event inode field is used only for comparison in queue merges and cannot be dereferenced after handle_event(), because it does not hold a refcount on the inode. Replace it with an abstract id to do the same thing. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 4 ++-- fs/notify/inotify/inotify_fsnotify.c | 4 ++-- fs/notify/inotify/inotify_user.c | 2 +- include/linux/fsnotify_backend.h | 7 +++---- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 19ec7a4f4d50..6a202aaf941f 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -26,7 +26,7 @@ static bool should_merge(struct fsnotify_event *old_fsn, old = FANOTIFY_E(old_fsn); new = FANOTIFY_E(new_fsn); - if (old_fsn->inode != new_fsn->inode || old->pid != new->pid || + if (old_fsn->objectid != new_fsn->objectid || old->pid != new->pid || old->fh_type != new->fh_type || old->fh_len != new->fh_len) return false; @@ -312,7 +312,7 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, if (!event) goto out; init: __maybe_unused - fsnotify_init_event(&event->fse, inode); + fsnotify_init_event(&event->fse, (unsigned long)inode); event->mask = mask; if (FAN_GROUP_FLAG(group, FAN_REPORT_TID)) event->pid = get_pid(task_pid(current)); diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 6bb98522bbfd..2ebc89047153 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -39,7 +39,7 @@ static bool event_compare(struct fsnotify_event *old_fsn, if (old->mask & FS_IN_IGNORED) return false; if ((old->mask == new->mask) && - (old_fsn->inode == new_fsn->inode) && + (old_fsn->objectid == new_fsn->objectid) && (old->name_len == new->name_len) && (!old->name_len || !strcmp(old->name, new->name))) return true; @@ -116,7 +116,7 @@ int inotify_handle_event(struct fsnotify_group *group, mask &= ~IN_ISDIR; fsn_event = &event->fse; - fsnotify_init_event(fsn_event, inode); + fsnotify_init_event(fsn_event, (unsigned long)inode); event->mask = mask; event->wd = i_mark->wd; event->sync_cookie = cookie; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 107537a543fd..81ffc8629fc4 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -635,7 +635,7 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events) return ERR_PTR(-ENOMEM); } group->overflow_event = &oevent->fse; - fsnotify_init_event(group->overflow_event, NULL); + fsnotify_init_event(group->overflow_event, 0); oevent->mask = FS_Q_OVERFLOW; oevent->wd = -1; oevent->sync_cookie = 0; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index ab0913619403..8ede512fca70 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -132,8 +132,7 @@ struct fsnotify_ops { */ struct fsnotify_event { struct list_head list; - /* inode may ONLY be dereferenced during handle_event(). */ - struct inode *inode; /* either the inode the event happened to or its parent */ + unsigned long objectid; /* identifier for queue merges */ }; /* @@ -543,10 +542,10 @@ extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info); extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); static inline void fsnotify_init_event(struct fsnotify_event *event, - struct inode *inode) + unsigned long objectid) { INIT_LIST_HEAD(&event->list); - event->inode = inode; + event->objectid = objectid; } #else From patchwork Thu Mar 19 15:10:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447479 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 90C93913 for ; Thu, 19 Mar 2020 15:10:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6F99F20CC7 for ; Thu, 19 Mar 2020 15:10:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VfKegURA" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727141AbgCSPKv (ORCPT ); Thu, 19 Mar 2020 11:10:51 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:40703 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727788AbgCSPKu (ORCPT ); Thu, 19 Mar 2020 11:10:50 -0400 Received: by mail-wm1-f67.google.com with SMTP id z12so2701425wmf.5 for ; Thu, 19 Mar 2020 08:10:49 -0700 (PDT) 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=Hw92EfxggEG70B0nQ2O8fMdQ77GBcOxSMBBaeFGaR3U=; b=VfKegURAKhBPON3k6ppAWK2c/4HFcTXNj1KpG8jzF5s24KNUQI6YfJVKU/U0pcRnRh S+WjnUYsSvmI5YGgz3tWsY7va4zPoltoKV8XKEhtscHzL0kK81QTU0E/IuxsCh5+fbqz mW/1pAGcUFEMikzY2oyjJdegdS/g+JHS4pDjUWrdEErzDi+NOIArhEfK7WODp2A6s0A7 hT0aLuN0aCaj3wl5wKra4Do2TRSWgC7oBo51HK72NsHDkx/zezIk1PTMk4Eb2hEk3EC4 t1w9zPmZrHREmPvnot/zfphDEB7IqlvKviAMea5vXbkxR0bKNwYvXPwGU/H9qfAtCCLy r2Qg== 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=Hw92EfxggEG70B0nQ2O8fMdQ77GBcOxSMBBaeFGaR3U=; b=ptbPgOLyDnA8vQ0HLJ47jhtia9zTpIZ89HdfrUsP0veheB3IyerOmSHyklb3nbp7Ah zvTuoNO/8ZS/PbR1GkK2kiIasAghoH2kETe8qq5ZpOiOx4JB/NusEkQpMyAekoGsBGyx ttnDSDIG7P8zJAFIeBsFGT2X9wMV9+DI/tXUl0JQZ7GVT6w1tXJ3FfoB2p7cjMpBt81Z pat9/eiq55iDVzq6La5+x5TlpIqqpUaJycIo76xcXLqYF4cHlwUpyBGoj9bbaDbvsaZA gJ+yv0f7Wb9XSOCgIzRjusnmpqmfzDT0nYnTj3AkLUyZYLxAa1V+T5CJTiXgaRGqB3pi Z2fg== X-Gm-Message-State: ANhLgQ3EkMYW+Av6PJRMdgwpmaC1/qxMMyjunfcaJ1v1zRl11n/v1iWo X9G5khP6sbIBhMBxn6xn/Hs= X-Google-Smtp-Source: ADFU+vvumBuursYBzo/Upn3RUiec2Fxxj/0PxwGEw2nKFnqSZ+rf9XdqJnrNJuDicxWgG6vyGKZaeA== X-Received: by 2002:a1c:68d5:: with SMTP id d204mr4253905wmc.15.1584630649123; Thu, 19 Mar 2020 08:10:49 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:48 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 08/14] fanotify: merge duplicate events on parent and child Date: Thu, 19 Mar 2020 17:10:16 +0200 Message-Id: <20200319151022.31456-9-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org With inotify, when a watch is set on a directory and on its child, an event on the child is reported twice, once with wd of the parent watch and once with wd of the child watch without the filename. With fanotify, when a watch is set on a directory and on its child, an event on the child is reported twice, but it has the exact same information - either an open file descriptor of the child or an encoded fid of the child. The reason that the two identical events are not merged is because the object id used for merging events in the queue is the child inode in one event and parent inode in the other. For events with path or dentry data, use the victim inode instead of the watched inode as the object id for event merging, so that the event reported on parent will be merged with the event reported on the child. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 6a202aaf941f..97d34b958761 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -312,7 +312,12 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, if (!event) goto out; init: __maybe_unused - fsnotify_init_event(&event->fse, (unsigned long)inode); + /* + * Use the victim inode instead of the watching inode as the id for + * event queue, so event reported on parent is merged with event + * reported on child when both directory and child watches exist. + */ + fsnotify_init_event(&event->fse, (unsigned long)id); event->mask = mask; if (FAN_GROUP_FLAG(group, FAN_REPORT_TID)) event->pid = get_pid(task_pid(current)); From patchwork Thu Mar 19 15:10:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447481 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 062756CA for ; Thu, 19 Mar 2020 15:10:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D9DDB20CC7 for ; Thu, 19 Mar 2020 15:10:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PuyJbTyS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727448AbgCSPK4 (ORCPT ); Thu, 19 Mar 2020 11:10:56 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:41134 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727346AbgCSPKz (ORCPT ); Thu, 19 Mar 2020 11:10:55 -0400 Received: by mail-wr1-f66.google.com with SMTP id h9so3454207wrc.8 for ; Thu, 19 Mar 2020 08:10:53 -0700 (PDT) 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=w1xX2G0MUM7HeNuAW4oTRGSKIxL6yWzRoF5wXGlP9us=; b=PuyJbTySMjtO3HwYvywOrD4yFhJhGNP+qkaFZUT1IcMiyXyJ9r/elK9SemD0ISIVZA oXCUcNHUC/JzbnQpySA662oS1bvi8VVTNT+V0RFiRbmoJHznGfwApAEutoCdEuOelZ0Q yMsB6JxlmcJatRGwLNlHHPn8Y0biIFQq70qFuryvMSxli8654bj8efzk9AWQd+TFydjG PedN6DDnP1OiR0653yNTUubyTbWfhTvG6f8udkoN7P+zSlcGFgy3v28rNFTd46VQv3BU z5JjguYYnGkj1qqMdDeTehjp1w0Lzpp8CuzZDTpUUxJrMeh2vaIkN8tuTrSs74KRZhPl 7mtA== 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=w1xX2G0MUM7HeNuAW4oTRGSKIxL6yWzRoF5wXGlP9us=; b=NI4jLc8kbBxjZK0oFjSrTTl7whC2+SeFTX+Z5hzFgHnHe3GJHRYGpv/Qgs9K20chKx jlcOkFQUJ/8329xVmX02BMwkbNfWUViSLC9MAh1O0Vg8jl6EgrlpD5rhLJ30v0pmfWQH SBOuh/ZkCbZfOizbBSj6/L4CICl0V0/MVy+FXRR8n+RnveEoFnjGGBrYW2IFWQxQzPyB TQdZ1DybhSrip6rGf0pB8Lj5NVcDcyasxFcOd5p5iNP2DUN3xsOk8Yo0fzeCYoAFf2j3 Uap0B+DX27GpvI/Or6KRbfC9mN1E3Q340hJ+vuRizPPD9UpnJy13/4rhQwVwasc3WMW4 PCgA== X-Gm-Message-State: ANhLgQ1pchHEDbaYKBucZtV/mSAePpr5s6UDlQZCQefaTZuVd7ijscUk qTvee8Qrr5fEppuAkqXM2GM= X-Google-Smtp-Source: ADFU+vt+yhEeifFVTmVk8zAmNAyrQbIMruNuu7Zn0qbqJUZ3VB5i985osin2LnC4Mqf1JZt2Nwa8Zw== X-Received: by 2002:a5d:6091:: with SMTP id w17mr4806771wrt.402.1584630652802; Thu, 19 Mar 2020 08:10:52 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:52 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 09/14] fanotify: fix merging marks masks with FAN_ONDIR Date: Thu, 19 Mar 2020 17:10:17 +0200 Message-Id: <20200319151022.31456-10-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Change the logic of FAN_ONDIR in two ways that are similar to the logic of FAN_EVENT_ON_CHILD, that was fixed in commit 54a307ba8d3c ("fanotify: fix logic of events on child"): 1. The flag is meaningless in ignore mask 2. The flag refers only to events in the mask of the mark where it is set This is what the fanotify_mark.2 man page says about FAN_ONDIR: "Without this flag, only events for files are created." It doesn't say anything about setting this flag in ignore mask to stop getting events on directories nor can I think of any setup where this capability would be useful. Currently, when marks masks are merged, the FAN_ONDIR flag set in one mark affects the events that are set in another mark's mask and this behavior causes unexpected results. For example, a user adds a mark on a directory with mask FAN_ATTRIB | FAN_ONDIR and a mount mark with mask FAN_OPEN (without FAN_ONDIR). An opendir() of that directory (which is inside that mount) generates a FAN_OPEN event even though neither of the marks requested to get open events on directories. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 97d34b958761..960f4f4d9e8f 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -171,6 +171,13 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, if (!fsnotify_iter_should_report_type(iter_info, type)) continue; mark = iter_info->marks[type]; + /* + * If the event is on dir and this mark doesn't care about + * events on dir, don't send it! + */ + if (event_mask & FS_ISDIR && !(mark->mask & FS_ISDIR)) + continue; + /* * If the event is for a child and this mark doesn't care about * events on a child, don't send it! @@ -203,10 +210,6 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, user_mask &= ~FAN_ONDIR; } - if (event_mask & FS_ISDIR && - !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) - return 0; - return test_mask & user_mask; } From patchwork Thu Mar 19 15:10:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447483 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 35B58913 for ; Thu, 19 Mar 2020 15:10:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EBD4620BED for ; Thu, 19 Mar 2020 15:10:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="c7Klv0vN" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727801AbgCSPK6 (ORCPT ); Thu, 19 Mar 2020 11:10:58 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:46992 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727416AbgCSPK5 (ORCPT ); Thu, 19 Mar 2020 11:10:57 -0400 Received: by mail-wr1-f68.google.com with SMTP id j17so48500wru.13 for ; Thu, 19 Mar 2020 08:10:54 -0700 (PDT) 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=cb6lUWyfJYVDyB4wPMBGrg1wfAdW+cF1bQpBgq0CT7Y=; b=c7Klv0vNP99AyjdT4jr6H+7iiqfnKhXfBD4VFyXSSgd2m9P3Kp3gHCFXWMGlN3aTRp 7Dg5i8KXvX2S+zumbEMhOhUSGNhr6fwgVpuWc6sT3ximt84reRt2xXpYSDcQyplN9VWM zJDH1R19GK2mg383Rhif204i15wBnhoMGnvmm4g8Ll7Ha/aAnIe50SskxRarwqRYIzw4 3Wl1OYUMOYN+Ncr17uivP+WNFpM4Vgs1DSKljRHCz/dm3Sykzf3OQk/2pmvH2pGWYcBz 730fp549MDeLcvgAYA7XR4VSZmjbJyc/GniJ4PoTGI5/ptTr/4wXXymVmSV1vcxXigpd 5Y1A== 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=cb6lUWyfJYVDyB4wPMBGrg1wfAdW+cF1bQpBgq0CT7Y=; b=GU+TK7bIIwlD+rBsgg7amWxrQGqlYigxu22g57Q46qvhPZarXd899Q4fMR1CmjGoug VIHZ5xKGD0Zi8vz5W0OgJZoURbzBra8Mhkd2sjRRsQrs4AEHmSn/AzQlXq35PUe3GN8j oF2wNRVTnJXcdga9qyYRXorceTC9WWjEloCzVGgXH4gzaV6KKJm73emCNvIWHdyH0k4P mIkUVb06vyVbPdxXdpRiPNnEr+TtptpHua+f3R6gBO4nAR1vZNtbGSInR8i29vTL5uE/ BuPvEfohup1ksuVu18KN6ez5H5b3etzxO0J3AsxcDOXuqjPjHKJIye5a613iJZkHzJKf 6TSA== X-Gm-Message-State: ANhLgQ3jidlMrp3mhC4g/7lmEFs20uUyuNtx7kmr52YxJjFnAK3R0EdW J5j4U/HCTMnTUQqexinRvyg= X-Google-Smtp-Source: ADFU+vtye7kTva61Pwz0k9E9TfAz6os/mdPZe3n6bmVprHwdvcFdbEV7fw6DioovANaNiRvewK1kWg== X-Received: by 2002:a5d:5710:: with SMTP id a16mr4964015wrv.5.1584630654144; Thu, 19 Mar 2020 08:10:54 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:53 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 10/14] fanotify: divorce fanotify_path_event and fanotify_fid_event Date: Thu, 19 Mar 2020 17:10:18 +0200 Message-Id: <20200319151022.31456-11-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Breakup the union and make them both inherit from abstract fanotify_event. fanotify_path_event, fanotify_fid_event and fanotify_perm_event inherit from fanotify_event. type field in abstract fanotify_event determines the concrete event type. fanotify_path_event, fanotify_fid_event and fanotify_perm_event are allocated from separate memcache pools. The separation of struct fanotify_fid_hdr from the file handle that was done for efficient packing of fanotify_event is no longer needed, so re-group the file handle fields under struct fanotify_fh. The struct fanotify_fid, which served to group fsid and file handle for the union is no longer needed so break it up. Rename fanotify_perm_event casting macro to FANOTIFY_PERM(), so that FANOTIFY_PE() and FANOTIFY_FE() can be used as casting macros to fanotify_path_event and fanotify_fid_event. Suggested-by: Jan Kara Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 201 +++++++++++++++++++++-------- fs/notify/fanotify/fanotify.h | 146 ++++++++++++--------- fs/notify/fanotify/fanotify_user.c | 69 +++++----- 3 files changed, 265 insertions(+), 151 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 960f4f4d9e8f..4c5dd5db21bd 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -17,6 +17,42 @@ #include "fanotify.h" +static bool fanotify_path_equal(struct path *p1, struct path *p2) +{ + return p1->mnt == p2->mnt && p1->dentry == p2->dentry; +} + +static inline bool fanotify_fsid_equal(__kernel_fsid_t *fsid1, + __kernel_fsid_t *fsid2) +{ + return fsid1->val[0] == fsid1->val[0] && fsid2->val[1] == fsid2->val[1]; +} + +static bool fanotify_fh_equal(struct fanotify_fh *fh1, + struct fanotify_fh *fh2) +{ + if (fh1->type != fh2->type || fh1->len != fh2->len) + return false; + + /* Do not merge events if we failed to encode fh */ + if (fh1->type == FILEID_INVALID) + return false; + + return !fh1->len || + !memcmp(fanotify_fh_buf(fh1), fanotify_fh_buf(fh2), fh1->len); +} + +static bool fanotify_fid_event_equal(struct fanotify_fid_event *ffe1, + struct fanotify_fid_event *ffe2) +{ + /* Do not merge fid events without object fh */ + if (!ffe1->object_fh.len) + return false; + + return fanotify_fsid_equal(&ffe1->fsid, &ffe2->fsid) && + fanotify_fh_equal(&ffe1->object_fh, &ffe2->object_fh); +} + static bool should_merge(struct fsnotify_event *old_fsn, struct fsnotify_event *new_fsn) { @@ -26,14 +62,15 @@ static bool should_merge(struct fsnotify_event *old_fsn, old = FANOTIFY_E(old_fsn); new = FANOTIFY_E(new_fsn); - if (old_fsn->objectid != new_fsn->objectid || old->pid != new->pid || - old->fh_type != new->fh_type || old->fh_len != new->fh_len) + if (old_fsn->objectid != new_fsn->objectid || + old->type != new->type || old->pid != new->pid) return false; - if (fanotify_event_has_path(old)) { - return old->path.mnt == new->path.mnt && - old->path.dentry == new->path.dentry; - } else if (fanotify_event_has_fid(old)) { + switch (old->type) { + case FANOTIFY_EVENT_TYPE_PATH: + return fanotify_path_equal(fanotify_event_path(old), + fanotify_event_path(new)); + case FANOTIFY_EVENT_TYPE_FID: /* * We want to merge many dirent events in the same dir (i.e. * creates/unlinks/renames), but we do not want to merge dirent @@ -42,11 +79,15 @@ static bool should_merge(struct fsnotify_event *old_fsn, * mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+ * unlink pair or rmdir+create pair of events. */ - return (old->mask & FS_ISDIR) == (new->mask & FS_ISDIR) && - fanotify_fid_equal(&old->fid, &new->fid, old->fh_len); + if ((old->mask & FS_ISDIR) != (new->mask & FS_ISDIR)) + return false; + + return fanotify_fid_event_equal(FANOTIFY_FE(old), + FANOTIFY_FE(new)); + default: + WARN_ON_ONCE(1); } - /* Do not merge events if we failed to encode fid */ return false; } @@ -213,15 +254,14 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, return test_mask & user_mask; } -static int fanotify_encode_fid(struct fanotify_event *event, - struct inode *inode, gfp_t gfp, - __kernel_fsid_t *fsid) +static void fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, + gfp_t gfp) { - struct fanotify_fid *fid = &event->fid; - int dwords, bytes = 0; - int err, type; + int dwords, type, bytes = 0; + char *ext_buf = NULL; + void *buf = fh->buf; + int err; - fid->ext_fh = NULL; dwords = 0; err = -ENOENT; type = exportfs_encode_inode_fh(inode, NULL, &dwords, NULL); @@ -232,31 +272,32 @@ static int fanotify_encode_fid(struct fanotify_event *event, if (bytes > FANOTIFY_INLINE_FH_LEN) { /* Treat failure to allocate fh as failure to allocate event */ err = -ENOMEM; - fid->ext_fh = kmalloc(bytes, gfp); - if (!fid->ext_fh) + ext_buf = kmalloc(bytes, gfp); + if (!ext_buf) goto out_err; + + *fanotify_fh_ext_buf_ptr(fh) = ext_buf; + buf = ext_buf; } - type = exportfs_encode_inode_fh(inode, fanotify_fid_fh(fid, bytes), - &dwords, NULL); + type = exportfs_encode_inode_fh(inode, buf, &dwords, NULL); err = -EINVAL; if (!type || type == FILEID_INVALID || bytes != dwords << 2) goto out_err; - fid->fsid = *fsid; - event->fh_len = bytes; + fh->type = type; + fh->len = bytes; - return type; + return; out_err: - pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, " - "type=%d, bytes=%d, err=%i)\n", - fsid->val[0], fsid->val[1], type, bytes, err); - kfree(fid->ext_fh); - fid->ext_fh = NULL; - event->fh_len = 0; - - return FILEID_INVALID; + pr_warn_ratelimited("fanotify: failed to encode fid (type=%d, len=%d, err=%i)\n", + type, bytes, err); + kfree(ext_buf); + *fanotify_fh_ext_buf_ptr(fh) = NULL; + /* Report the event without a file identifier on encode error */ + fh->type = FILEID_INVALID; + fh->len = 0; } /* @@ -282,10 +323,17 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, __kernel_fsid_t *fsid) { struct fanotify_event *event = NULL; + struct fanotify_fid_event *ffe = NULL; gfp_t gfp = GFP_KERNEL_ACCOUNT; struct inode *id = fanotify_fid_inode(inode, mask, data, data_type); const struct path *path = fsnotify_data_path(data, data_type); + /* Make sure we can easily cast between inherited structs */ + BUILD_BUG_ON(offsetof(struct fanotify_event, fse) != 0); + BUILD_BUG_ON(offsetof(struct fanotify_fid_event, fae) != 0); + BUILD_BUG_ON(offsetof(struct fanotify_path_event, fae) != 0); + BUILD_BUG_ON(offsetof(struct fanotify_perm_event, fae) != 0); + /* * For queues with unlimited length lost events are not expected and * can possibly have security implications. Avoid losing events when @@ -306,14 +354,29 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp); if (!pevent) goto out; + event = &pevent->fae; + event->type = FANOTIFY_EVENT_TYPE_PATH_PERM; pevent->response = 0; pevent->state = FAN_EVENT_INIT; goto init; } - event = kmem_cache_alloc(fanotify_event_cachep, gfp); - if (!event) - goto out; + + if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { + ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp); + if (!ffe) + goto out; + + event = &ffe->fae; + event->type = FANOTIFY_EVENT_TYPE_FID; + } else { + event = kmem_cache_alloc(fanotify_path_event_cachep, gfp); + if (!event) + goto out; + + event->type = FANOTIFY_EVENT_TYPE_PATH; + } + init: __maybe_unused /* * Use the victim inode instead of the watching inode as the id for @@ -326,18 +389,22 @@ init: __maybe_unused event->pid = get_pid(task_pid(current)); else event->pid = get_pid(task_tgid(current)); - event->fh_len = 0; - 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, id, gfp, fsid); - } else if (path) { - event->fh_type = FILEID_ROOT; - event->path = *path; - path_get(path); - } else { - event->fh_type = FILEID_INVALID; - event->path.mnt = NULL; - event->path.dentry = NULL; + if (fanotify_event_has_fid(event)) { + ffe->object_fh.len = 0; + if (fsid) + ffe->fsid = *fsid; + if (id) + fanotify_encode_fh(&ffe->object_fh, id, gfp); + } else if (fanotify_event_has_path(event)) { + struct path *p = fanotify_event_path(event); + + if (path) { + *p = *path; + path_get(path); + } else { + p->mnt = NULL; + p->dentry = NULL; + } } out: memalloc_unuse_memcg(); @@ -457,7 +524,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, ret = 0; } else if (fanotify_is_perm_event(mask)) { - ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event), + ret = fanotify_get_response(group, FANOTIFY_PERM(fsn_event), iter_info); } finish: @@ -476,22 +543,44 @@ static void fanotify_free_group_priv(struct fsnotify_group *group) free_uid(user); } +static void fanotify_free_path_event(struct fanotify_event *event) +{ + path_put(fanotify_event_path(event)); + kmem_cache_free(fanotify_path_event_cachep, event); +} + +static void fanotify_free_perm_event(struct fanotify_event *event) +{ + path_put(fanotify_event_path(event)); + kmem_cache_free(fanotify_perm_event_cachep, event); +} + +static void fanotify_free_fid_event(struct fanotify_fid_event *ffe) +{ + if (fanotify_fh_has_ext_buf(&ffe->object_fh)) + kfree(fanotify_fh_ext_buf(&ffe->object_fh)); + kmem_cache_free(fanotify_fid_event_cachep, ffe); +} + static void fanotify_free_event(struct fsnotify_event *fsn_event) { struct fanotify_event *event; event = FANOTIFY_E(fsn_event); - if (fanotify_event_has_path(event)) - path_put(&event->path); - else if (fanotify_event_has_ext_fh(event)) - kfree(event->fid.ext_fh); put_pid(event->pid); - if (fanotify_is_perm_event(event->mask)) { - kmem_cache_free(fanotify_perm_event_cachep, - FANOTIFY_PE(fsn_event)); - return; + switch (event->type) { + case FANOTIFY_EVENT_TYPE_PATH: + fanotify_free_path_event(event); + break; + case FANOTIFY_EVENT_TYPE_PATH_PERM: + fanotify_free_perm_event(event); + break; + case FANOTIFY_EVENT_TYPE_FID: + fanotify_free_fid_event(FANOTIFY_FE(event)); + break; + default: + WARN_ON_ONCE(1); } - kmem_cache_free(fanotify_event_cachep, event); } static void fanotify_free_mark(struct fsnotify_mark *fsn_mark) diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 68b30504284c..1bc73a65d9d2 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h @@ -5,7 +5,8 @@ #include extern struct kmem_cache *fanotify_mark_cache; -extern struct kmem_cache *fanotify_event_cachep; +extern struct kmem_cache *fanotify_fid_event_cachep; +extern struct kmem_cache *fanotify_path_event_cachep; extern struct kmem_cache *fanotify_perm_event_cachep; /* Possible states of the permission event */ @@ -18,96 +19,102 @@ enum { /* * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation). - * For 32bit arch, fid increases the size of fanotify_event by 12 bytes and - * fh_* fields increase the size of fanotify_event by another 4 bytes. - * For 64bit arch, fid increases the size of fanotify_fid by 8 bytes and - * fh_* fields are packed in a hole after mask. + * fh buf should be dword aligned. On 64bit arch, the ext_buf pointer is + * stored in either the first or last 2 dwords. */ -#if BITS_PER_LONG == 32 #define FANOTIFY_INLINE_FH_LEN (3 << 2) -#else -#define FANOTIFY_INLINE_FH_LEN (4 << 2) -#endif -struct fanotify_fid { - __kernel_fsid_t fsid; - union { - unsigned char fh[FANOTIFY_INLINE_FH_LEN]; - unsigned char *ext_fh; - }; -}; +struct fanotify_fh { + unsigned char buf[FANOTIFY_INLINE_FH_LEN]; + u8 type; + u8 len; +} __aligned(4); + +static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh) +{ + return fh->len > FANOTIFY_INLINE_FH_LEN; +} + +static inline char **fanotify_fh_ext_buf_ptr(struct fanotify_fh *fh) +{ + BUILD_BUG_ON(__alignof__(char *) - 4 + sizeof(char *) > + FANOTIFY_INLINE_FH_LEN); + return (char **)ALIGN((unsigned long)(fh->buf), __alignof__(char *)); +} -static inline void *fanotify_fid_fh(struct fanotify_fid *fid, - unsigned int fh_len) +static inline void *fanotify_fh_ext_buf(struct fanotify_fh *fh) { - return fh_len <= FANOTIFY_INLINE_FH_LEN ? fid->fh : fid->ext_fh; + return *fanotify_fh_ext_buf_ptr(fh); } -static inline bool fanotify_fid_equal(struct fanotify_fid *fid1, - struct fanotify_fid *fid2, - unsigned int fh_len) +static inline void *fanotify_fh_buf(struct fanotify_fh *fh) { - return fid1->fsid.val[0] == fid2->fsid.val[0] && - fid1->fsid.val[1] == fid2->fsid.val[1] && - !memcmp(fanotify_fid_fh(fid1, fh_len), - fanotify_fid_fh(fid2, fh_len), fh_len); + return fanotify_fh_has_ext_buf(fh) ? fanotify_fh_ext_buf(fh) : fh->buf; } /* - * Structure for normal fanotify events. It gets allocated in + * Common structure for fanotify events. Concrete structs are allocated in * fanotify_handle_event() and freed when the information is retrieved by - * userspace + * userspace. The type of event determines how it was allocated, how it will + * be freed and which concrete struct it may be cast to. */ +enum fanotify_event_type { + FANOTIFY_EVENT_TYPE_FID, + FANOTIFY_EVENT_TYPE_PATH, + FANOTIFY_EVENT_TYPE_PATH_PERM, +}; + struct fanotify_event { struct fsnotify_event fse; u32 mask; - /* - * Those fields are outside fanotify_fid to pack fanotify_event nicely - * on 64bit arch and to use fh_type as an indication of whether path - * or fid are used in the union: - * FILEID_ROOT (0) for path, > 0 for fid, FILEID_INVALID for neither. - */ - u8 fh_type; - u8 fh_len; - u16 pad; - union { - /* - * We hold ref to this path so it may be dereferenced at any - * point during this object's lifetime - */ - struct path path; - /* - * With FAN_REPORT_FID, we do not hold any reference on the - * victim object. Instead we store its NFS file handle and its - * filesystem's fsid as a unique identifier. - */ - struct fanotify_fid fid; - }; + enum fanotify_event_type type; struct pid *pid; }; -static inline bool fanotify_event_has_path(struct fanotify_event *event) +struct fanotify_fid_event { + struct fanotify_event fae; + __kernel_fsid_t fsid; + struct fanotify_fh object_fh; +}; + +#define FANOTIFY_FE(event) ((struct fanotify_fid_event *)(event)) + +static inline bool fanotify_event_has_fid(struct fanotify_event *event) { - return event->fh_type == FILEID_ROOT; + return event->type == FANOTIFY_EVENT_TYPE_FID; } -static inline bool fanotify_event_has_fid(struct fanotify_event *event) +static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event) { - return event->fh_type != FILEID_ROOT && - event->fh_type != FILEID_INVALID; + if (event->type == FANOTIFY_EVENT_TYPE_FID) + return &FANOTIFY_FE(event)->fsid; + else + return NULL; } -static inline bool fanotify_event_has_ext_fh(struct fanotify_event *event) +static inline struct fanotify_fh *fanotify_event_object_fh( + struct fanotify_event *event) { - return fanotify_event_has_fid(event) && - event->fh_len > FANOTIFY_INLINE_FH_LEN; + if (event->type == FANOTIFY_EVENT_TYPE_FID) + return &FANOTIFY_FE(event)->object_fh; + else + return NULL; } -static inline void *fanotify_event_fh(struct fanotify_event *event) +static inline int fanotify_event_object_fh_len(struct fanotify_event *event) { - return fanotify_fid_fh(&event->fid, event->fh_len); + struct fanotify_fh *fh = fanotify_event_object_fh(event); + + return fh ? fh->len : 0; } +struct fanotify_path_event { + struct fanotify_event fae; + struct path path; +}; + +#define FANOTIFY_PE(event) ((struct fanotify_path_event *)(event)) + /* * Structure for permission fanotify events. It gets allocated and freed in * fanotify_handle_event() since we wait there for user response. When the @@ -117,13 +124,14 @@ static inline void *fanotify_event_fh(struct fanotify_event *event) */ struct fanotify_perm_event { struct fanotify_event fae; + struct path path; unsigned short response; /* userspace answer to the event */ unsigned short state; /* state of the event */ int fd; /* fd we passed to userspace for this event */ }; static inline struct fanotify_perm_event * -FANOTIFY_PE(struct fsnotify_event *fse) +FANOTIFY_PERM(struct fsnotify_event *fse) { return container_of(fse, struct fanotify_perm_event, fae.fse); } @@ -139,6 +147,22 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse) return container_of(fse, struct fanotify_event, fse); } +static inline bool fanotify_event_has_path(struct fanotify_event *event) +{ + return event->type == FANOTIFY_EVENT_TYPE_PATH || + event->type == FANOTIFY_EVENT_TYPE_PATH_PERM; +} + +static inline struct path *fanotify_event_path(struct fanotify_event *event) +{ + if (event->type == FANOTIFY_EVENT_TYPE_PATH) + return &FANOTIFY_PE(event)->path; + else if (event->type == FANOTIFY_EVENT_TYPE_PATH_PERM) + return &((struct fanotify_perm_event *)event)->path; + else + return NULL; +} + struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, struct inode *inode, u32 mask, const void *data, int data_type, diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 0aa362b88550..6d30627863ff 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -46,18 +46,21 @@ extern const struct fsnotify_ops fanotify_fsnotify_ops; struct kmem_cache *fanotify_mark_cache __read_mostly; -struct kmem_cache *fanotify_event_cachep __read_mostly; +struct kmem_cache *fanotify_fid_event_cachep __read_mostly; +struct kmem_cache *fanotify_path_event_cachep __read_mostly; struct kmem_cache *fanotify_perm_event_cachep __read_mostly; #define FANOTIFY_EVENT_ALIGN 4 static int fanotify_event_info_len(struct fanotify_event *event) { - if (!fanotify_event_has_fid(event)) + int fh_len = fanotify_event_object_fh_len(event); + + if (!fh_len) return 0; return roundup(sizeof(struct fanotify_event_info_fid) + - sizeof(struct file_handle) + event->fh_len, + sizeof(struct file_handle) + fh_len, FANOTIFY_EVENT_ALIGN); } @@ -90,20 +93,19 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group, } fsn_event = fsnotify_remove_first_event(group); if (fanotify_is_perm_event(FANOTIFY_E(fsn_event)->mask)) - FANOTIFY_PE(fsn_event)->state = FAN_EVENT_REPORTED; + FANOTIFY_PERM(fsn_event)->state = FAN_EVENT_REPORTED; out: spin_unlock(&group->notification_lock); return fsn_event; } -static int create_fd(struct fsnotify_group *group, - struct fanotify_event *event, +static int create_fd(struct fsnotify_group *group, struct path *path, struct file **file) { int client_fd; struct file *new_file; - pr_debug("%s: group=%p event=%p\n", __func__, group, event); + pr_debug("%s: group=%p path=%p\n", __func__, group, path); client_fd = get_unused_fd_flags(group->fanotify_data.f_flags); if (client_fd < 0) @@ -113,14 +115,9 @@ static int create_fd(struct fsnotify_group *group, * we need a new file handle for the userspace program so it can read even if it was * originally opened O_WRONLY. */ - /* it's possible this event was an overflow event. in that case dentry and mnt - * are NULL; That's fine, just don't call dentry open */ - if (event->path.dentry && event->path.mnt) - new_file = dentry_open(&event->path, - group->fanotify_data.f_flags | FMODE_NONOTIFY, - current_cred()); - else - new_file = ERR_PTR(-EOVERFLOW); + new_file = dentry_open(path, + group->fanotify_data.f_flags | FMODE_NONOTIFY, + current_cred()); if (IS_ERR(new_file)) { /* * we still send an event even if we can't open the file. this @@ -208,8 +205,9 @@ static int copy_fid_to_user(struct fanotify_event *event, char __user *buf) { struct fanotify_event_info_fid info = { }; struct file_handle handle = { }; - unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh; - size_t fh_len = event->fh_len; + unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf; + struct fanotify_fh *fh = fanotify_event_object_fh(event); + size_t fh_len = fh->len; size_t len = fanotify_event_info_len(event); if (!len) @@ -221,13 +219,13 @@ static int copy_fid_to_user(struct fanotify_event *event, char __user *buf) /* 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; + info.fsid = *fanotify_event_fsid(event); if (copy_to_user(buf, &info, sizeof(info))) return -EFAULT; buf += sizeof(info); len -= sizeof(info); - handle.handle_type = event->fh_type; + handle.handle_type = fh->type; handle.handle_bytes = fh_len; if (copy_to_user(buf, &handle, sizeof(handle))) return -EFAULT; @@ -238,12 +236,12 @@ static int copy_fid_to_user(struct fanotify_event *event, char __user *buf) * For an inline fh, copy through stack to exclude the copy from * usercopy hardening protections. */ - fh = fanotify_event_fh(event); + fh_buf = fanotify_fh_buf(fh); if (fh_len <= FANOTIFY_INLINE_FH_LEN) { - memcpy(bounce, fh, fh_len); - fh = bounce; + memcpy(bounce, fh_buf, fh_len); + fh_buf = bounce; } - if (copy_to_user(buf, fh, fh_len)) + if (copy_to_user(buf, fh_buf, fh_len)) return -EFAULT; /* Pad with 0's */ @@ -261,13 +259,13 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, char __user *buf, size_t count) { struct fanotify_event_metadata metadata; - struct fanotify_event *event; + struct fanotify_event *event = FANOTIFY_E(fsn_event); + struct path *path = fanotify_event_path(event); struct file *f = NULL; int ret, fd = FAN_NOFD; pr_debug("%s: group=%p event=%p\n", __func__, group, fsn_event); - event = container_of(fsn_event, struct fanotify_event, fse); metadata.event_len = FAN_EVENT_METADATA_LEN; metadata.metadata_len = FAN_EVENT_METADATA_LEN; metadata.vers = FANOTIFY_METADATA_VERSION; @@ -275,12 +273,12 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS; metadata.pid = pid_vnr(event->pid); - if (fanotify_event_has_path(event)) { - fd = create_fd(group, event, &f); + if (fanotify_event_has_fid(event)) { + metadata.event_len += fanotify_event_info_len(event); + } else if (path && path->mnt && path->dentry) { + fd = create_fd(group, path, &f); if (fd < 0) return fd; - } else if (fanotify_event_has_fid(event)) { - metadata.event_len += fanotify_event_info_len(event); } metadata.fd = fd; @@ -296,9 +294,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, goto out_close_fd; if (fanotify_is_perm_event(event->mask)) - FANOTIFY_PE(fsn_event)->fd = fd; + FANOTIFY_PERM(fsn_event)->fd = fd; - if (fanotify_event_has_path(event)) { + if (f) { fd_install(fd, f); } else if (fanotify_event_has_fid(event)) { ret = copy_fid_to_user(event, buf + FAN_EVENT_METADATA_LEN); @@ -390,7 +388,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, if (ret <= 0) { spin_lock(&group->notification_lock); finish_permission_event(group, - FANOTIFY_PE(kevent), FAN_DENY); + FANOTIFY_PERM(kevent), FAN_DENY); wake_up(&group->fanotify_data.access_waitq); } else { spin_lock(&group->notification_lock); @@ -474,7 +472,7 @@ static int fanotify_release(struct inode *ignored, struct file *file) spin_unlock(&group->notification_lock); fsnotify_destroy_event(group, fsn_event); } else { - finish_permission_event(group, FANOTIFY_PE(fsn_event), + finish_permission_event(group, FANOTIFY_PERM(fsn_event), FAN_ALLOW); } spin_lock(&group->notification_lock); @@ -1139,7 +1137,10 @@ static int __init fanotify_user_setup(void) fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, SLAB_PANIC|SLAB_ACCOUNT); - fanotify_event_cachep = KMEM_CACHE(fanotify_event, SLAB_PANIC); + fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event, + SLAB_PANIC); + fanotify_path_event_cachep = KMEM_CACHE(fanotify_path_event, + SLAB_PANIC); if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) { fanotify_perm_event_cachep = KMEM_CACHE(fanotify_perm_event, SLAB_PANIC); From patchwork Thu Mar 19 15:10:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447485 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 76FF1139A for ; Thu, 19 Mar 2020 15:10:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 561D620BED for ; Thu, 19 Mar 2020 15:10:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KKVU0o3M" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727804AbgCSPK6 (ORCPT ); Thu, 19 Mar 2020 11:10:58 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:33607 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727346AbgCSPK5 (ORCPT ); Thu, 19 Mar 2020 11:10:57 -0400 Received: by mail-wr1-f67.google.com with SMTP id a25so3507963wrd.0 for ; Thu, 19 Mar 2020 08:10:56 -0700 (PDT) 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=kVSVVobZ3NjP89BLt5Dp1KlPOZoxksqI1G3vxFASu/4=; b=KKVU0o3M/md4tmP1+HGj2DzLaLB5sQLd/vDRIvtKvVb9WrVGym+jxVWF6bKADrdAEb otY/YEOMPGfStWEs3A/V3xK9qerlvE4nP9A10Ve6iKOE6c/9HELBbJbGxVhZyfGaWyxl wPK02uvZu3S4fWxQUAU+rITWopbG9Ndpq3lGWJl09LJS1uVfwuVq/ESzZvw025Kn1vqX zW8YSZwK/d+MbJxfb+ASHmq94ASouWHapag4jmO0UQid7jJi8nbuooOLFhzDzD1IxN/0 xzlpvcLlxFVBXsoAz7TufLLU5MO6iNr0iZ/ykWE0jrj7QfK20BbUTYasGs8wPPXXfYhR Vf5g== 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=kVSVVobZ3NjP89BLt5Dp1KlPOZoxksqI1G3vxFASu/4=; b=nKi5TnZT+qLCIz0ki277CRxYopQRV9zhHS+u+oiwNNharygXQWSEN2EvCwFrzz7aJD 7TAjBpZvt+uU6IWQVyrv6wTUguXotqc7tZQlYXyR0wppXortmSsWoIl/8+qGMoRbOTmG mvkoXb1D41F+BEhaJj6tenfZmKN2FN4FSHxuQgJOMlosQm1ev4so9rttq8iwKTFtRkAd a/oTYO/HrAVQVnWxN12ulLtxwiAKrkqPuX14GPmGDNi4Z2SUTJE1rfJ4yN8JByNCv/ug SNIOwbyYp+ZCf4erjiklEPQkRlRGf0b9FjpVg7E3i5CKwdcNoUE6KSxIa4rYW8PJHxq7 na5g== X-Gm-Message-State: ANhLgQ221r758nXEi5cBNc+0QGJVyiiAshapaufPt18CjMhOs1lSMSKY zoOXeHyFvGEieqs7uCB50ieFCmOo X-Google-Smtp-Source: ADFU+vtjQAne+tFf51iwRqe1JffVtK36zPJY/uTGNenjRfNq6Ko0JADwciHMFupR3ll1XQbvVIus8w== X-Received: by 2002:a5d:4146:: with SMTP id c6mr4621995wrq.181.1584630655648; Thu, 19 Mar 2020 08:10:55 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:55 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 11/14] fanotify: send FAN_DIR_MODIFY event flavor with dir inode and name Date: Thu, 19 Mar 2020 17:10:19 +0200 Message-Id: <20200319151022.31456-12-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Dirent events are going to be supported in two flavors: 1. Directory fid info + mask that includes the specific event types (e.g. FAN_CREATE) and an optional FAN_ONDIR flag. 2. Directory fid info + name + mask that includes only FAN_DIR_MODIFY. To request the second event flavor, user needs to set the event type FAN_DIR_MODIFY in the mark mask. The first flavor is supported since kernel v5.1 for groups initialized with flag FAN_REPORT_FID. It is intended to be used for watching directories in "batch mode" - the watcher is notified when directory is changed and re-scans the directory content in response. This event flavor is stored more compactly in the event queue, so it is optimal for workloads with frequent directory changes. The second event flavor is intended to be used for watching large directories, where the cost of re-scan of the directory on every change is considered too high. The watcher getting the event with the directory fid and entry name is expected to call fstatat(2) to query the content of the entry after the change. Legacy inotify events are reported with name and event mask (e.g. "foo", FAN_CREATE | FAN_ONDIR). That can lead users to the conclusion that there is *currently* an entry "foo" that is a sub-directory, when in fact "foo" may be negative or non-dir by the time user gets the event. To make it clear that the current state of the named entry is unknown, when reporting an event with name info, fanotify obfuscates the specific event types (e.g. create,delete,rename) and uses a common event type - FAN_DIR_MODIFY to decribe the change. This should make it harder for users to make wrong assumptions and write buggy filesystem monitors. At this point, name info reporting is not yet implemented, so trying to set FAN_DIR_MODIFY in mark mask will return -EINVAL. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 7 ++++--- fs/notify/fsnotify.c | 2 +- include/linux/fsnotify.h | 6 ++++++ include/linux/fsnotify_backend.h | 4 +++- include/uapi/linux/fanotify.h | 1 + 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 4c5dd5db21bd..75f288d5eeab 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -235,9 +235,9 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, test_mask = event_mask & marks_mask & ~marks_ignored_mask; /* - * dirent modification events (create/delete/move) do not carry the - * child entry name/inode information. Instead, we report FAN_ONDIR - * for mkdir/rmdir so user can differentiate them from creat/unlink. + * For dirent modification events (create/delete/move) that do not carry + * the child entry name information, we report FAN_ONDIR for mkdir/rmdir + * so user can differentiate them from creat/unlink. * * For backward compatibility and consistency, do not report FAN_ONDIR * to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR @@ -465,6 +465,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(FAN_MOVED_FROM != FS_MOVED_FROM); BUILD_BUG_ON(FAN_CREATE != FS_CREATE); BUILD_BUG_ON(FAN_DELETE != FS_DELETE); + BUILD_BUG_ON(FAN_DIR_MODIFY != FS_DIR_MODIFY); BUILD_BUG_ON(FAN_DELETE_SELF != FS_DELETE_SELF); BUILD_BUG_ON(FAN_MOVE_SELF != FS_MOVE_SELF); BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD); diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 193530f57963..72d332ce8e12 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -383,7 +383,7 @@ static __init int fsnotify_init(void) { int ret; - BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 25); + BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 26); ret = init_srcu_struct(&fsnotify_mark_srcu); if (ret) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index d286663fcef2..b3d3f2ac34d5 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -30,6 +30,12 @@ static inline void fsnotify_name(struct inode *dir, __u32 mask, const struct qstr *name, u32 cookie) { fsnotify(dir, mask, child, FSNOTIFY_EVENT_INODE, name, cookie); + /* + * Send another flavor of the event without child inode data and + * without the specific event type (e.g. FS_CREATE|FS_IS_DIR). + * The name is relative to the dir inode the event is reported to. + */ + fsnotify(dir, FS_DIR_MODIFY, dir, FSNOTIFY_EVENT_INODE, name, 0); } static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 8ede512fca70..0019cb5f0113 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -47,6 +47,7 @@ #define FS_OPEN_PERM 0x00010000 /* open event in an permission hook */ #define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */ #define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */ +#define FS_DIR_MODIFY 0x00080000 /* Directory entry was modified */ #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ /* This inode cares about things that happen to its children. Always set for @@ -66,7 +67,8 @@ * The watching parent may get an FS_ATTRIB|FS_EVENT_ON_CHILD event * when a directory entry inside a child subdir changes. */ -#define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE) +#define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE | \ + FS_DIR_MODIFY) #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \ FS_OPEN_EXEC_PERM) diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index 2a1844edda47..615fa2c87179 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h @@ -24,6 +24,7 @@ #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ #define FAN_OPEN_EXEC_PERM 0x00040000 /* File open/exec in perm check */ +#define FAN_DIR_MODIFY 0x00080000 /* Directory entry was modified */ #define FAN_EVENT_ON_CHILD 0x08000000 /* Interested in child events */ From patchwork Thu Mar 19 15:10:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447487 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2EEBB6CA for ; Thu, 19 Mar 2020 15:11:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0E01A20BED for ; Thu, 19 Mar 2020 15:11:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="idyZCh13" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727830AbgCSPK7 (ORCPT ); Thu, 19 Mar 2020 11:10:59 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:45269 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727788AbgCSPK6 (ORCPT ); Thu, 19 Mar 2020 11:10:58 -0400 Received: by mail-wr1-f67.google.com with SMTP id i9so3430741wrx.12 for ; Thu, 19 Mar 2020 08:10:57 -0700 (PDT) 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=yAZeufZMP3+VvqXvebjKcn41g+hLAj10HPMbH884iL0=; b=idyZCh13m1OC84VA8MbbnSrOie7Qvr5EocH0+ceJdunNb4o/juuBM1XZaCSMXOKOn0 ZmxaCbox+qdW9QD8LtgxoFXruUtUyt0EKdeK+CzE9puxeUqM/O7Hfv1JvWtg/rTX1RHg VMutTx+TAQV5owuYOicVO3MR38xv8mxqGe1kS7AOnECTK5ejQMod24lOhv6GVCVlLnJX 7ltDOZwTRzZdOdfBsqe1q63vmpxtuVPKL87F8DnEY6RQGLnKYKpa8B7we3PWeotuiW5o PjbHDCwvgZ6ZWNNZb7qFvk6WQQglHxG9GcE01U3xYU1CdJWZlguGMa7XnIIBWmC1dzl0 jNFA== 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=yAZeufZMP3+VvqXvebjKcn41g+hLAj10HPMbH884iL0=; b=MMbWdqkcOjeQnXMYeYpkEvdpsiNjOMjxeYApwem7YysL3tM0H81NZdgZDquWAbBp3w pcqkKLX5OaCQdzrxmCIg06XvqyJU8znyuIIZMVz44u6br04yLqyg1cD1YFcBmPGxEnOd AfvVwn4NK4+zx6LHhvSZB+WZXpTQDCbI3jpBwfJMixxyrZWOJHNuvvfUbUvRkY7Pb308 KCxt0UJXHzs19IWdBQQad06OwREHKuGz3r3+POiU170LtRc+kY7zK2xnbqMd3UoaP/nb UvqbgcZ0K4/hwtE61N+4wGusc9KdEnazibyLovKT3hfkVYwOmK+xdQOlcz0rlBjYzx1c D2QQ== X-Gm-Message-State: ANhLgQ3FWGxd7Tz2Ls+r4ur59Dk6esJqVlKu9gqAz/5wfEpqTI1D0pCN SFuJG+fhsuT0Rrn4uZy0xws= X-Google-Smtp-Source: ADFU+vvIheUXyduJCZfmgGloXJDfqz3v8LyAsn1V6Z9GD0iYRKEePs5Tgc5zls/j1IJvR0kFIncYIw== X-Received: by 2002:a5d:6ca7:: with SMTP id a7mr5227202wra.157.1584630656934; Thu, 19 Mar 2020 08:10:56 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:56 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 12/14] fanotify: prepare to report both parent and child fid's Date: Thu, 19 Mar 2020 17:10:20 +0200 Message-Id: <20200319151022.31456-13-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org For some events, we are going to report both child and parent fid's, so pass fsid and file handle as arguments to copy_fid_to_user(), which is going to be called with parent and child file handles. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify_user.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 6d30627863ff..aaa62bd2b80e 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -52,6 +52,13 @@ struct kmem_cache *fanotify_perm_event_cachep __read_mostly; #define FANOTIFY_EVENT_ALIGN 4 +static int fanotify_fid_info_len(int fh_len) +{ + return roundup(sizeof(struct fanotify_event_info_fid) + + sizeof(struct file_handle) + fh_len, + FANOTIFY_EVENT_ALIGN); +} + static int fanotify_event_info_len(struct fanotify_event *event) { int fh_len = fanotify_event_object_fh_len(event); @@ -59,9 +66,7 @@ static int fanotify_event_info_len(struct fanotify_event *event) if (!fh_len) return 0; - return roundup(sizeof(struct fanotify_event_info_fid) + - sizeof(struct file_handle) + fh_len, - FANOTIFY_EVENT_ALIGN); + return fanotify_fid_info_len(fh_len); } /* @@ -201,14 +206,14 @@ static int process_access_response(struct fsnotify_group *group, return -ENOENT; } -static int copy_fid_to_user(struct fanotify_event *event, char __user *buf) +static int copy_fid_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, + char __user *buf) { struct fanotify_event_info_fid info = { }; struct file_handle handle = { }; unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf; - struct fanotify_fh *fh = fanotify_event_object_fh(event); size_t fh_len = fh->len; - size_t len = fanotify_event_info_len(event); + size_t len = fanotify_fid_info_len(fh_len); if (!len) return 0; @@ -219,7 +224,7 @@ static int copy_fid_to_user(struct fanotify_event *event, char __user *buf) /* 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 = *fanotify_event_fsid(event); + info.fsid = *fsid; if (copy_to_user(buf, &info, sizeof(info))) return -EFAULT; @@ -299,7 +304,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, if (f) { fd_install(fd, f); } else if (fanotify_event_has_fid(event)) { - ret = copy_fid_to_user(event, buf + FAN_EVENT_METADATA_LEN); + ret = copy_fid_to_user(fanotify_event_fsid(event), + fanotify_event_object_fh(event), + buf + FAN_EVENT_METADATA_LEN); if (ret < 0) return ret; } From patchwork Thu Mar 19 15:10:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447489 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D68BF6CA for ; Thu, 19 Mar 2020 15:11:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AB00920BED for ; Thu, 19 Mar 2020 15:11:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HOs3Ey06" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727858AbgCSPLC (ORCPT ); Thu, 19 Mar 2020 11:11:02 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:47006 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727346AbgCSPLB (ORCPT ); Thu, 19 Mar 2020 11:11:01 -0400 Received: by mail-wr1-f66.google.com with SMTP id j17so48873wru.13 for ; Thu, 19 Mar 2020 08:10:59 -0700 (PDT) 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=CtHfAwfUEi7SnYcHveXEghZQlOsnr1jNNb/hFvoEbh0=; b=HOs3Ey06fjKdPDuoL2dj7SF6GZvfrOfConXGatZu0gUxi4amvdFAfebGCgQ9NnG5Yj ii8lReWLqk+KrxkuHvnDIEIyZIC9RhVy1tafJbnD1Zjql5o/LihpPlxGDG1btL9DGdr1 d52TkwnOdVE7rAfAYAkYflVcywuH2Et5eGHgtwJBYNYGnEqpDuSO+67t2ZwFNLPW2nKy OqsNyyzZXj6siJVYq6cJwNzeLdElJXZJs28gnTHTYlXTWflGMSeopuSrATXfCNuvOgLu 7LMDuY1h/GmWL/L2iaQjv5hQUQdniax+NsuL5lSs/qlHsBPPfbwt38XNV/uv6fFEvSsc llQQ== 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=CtHfAwfUEi7SnYcHveXEghZQlOsnr1jNNb/hFvoEbh0=; b=LinGZG1CYl/9uibs/jTAhRQ9kMWqHe+SG/0Uxj6tVFqZznNgu23GC7IpoAHq/99lVk TMCT54ZRWt5hlNDNmaGVaw0MxdPhR0tg6SAbAu173nsEuQ7VuEEktF20AXAOId7CU0ML gYJ95dbHR5/hlaHCY99T6uR1XBdF4kI3MEaVWJpYdGh0e0po5eus8b/71DOj6OuqCvJL n32I2r++QBjQAx6OIOtTB9MQ7C8k47WFgzY0G5Sdzn06IhfrxJkRpCJ+41FtU2KDTZlm 2p19CwuXxskoZe4SQ78nWNQWkUBsVv+TUnygrVm34udKyjVU0emuRPCA6eayAI12Cbx+ LDQA== X-Gm-Message-State: ANhLgQ0YZXLVI4ULs2ACMEUO04S2RBQIqsw5Pqv4Hx0COnxIjUF1n6d2 F6eKtaAO1vAI1ThTHLXT9OI= X-Google-Smtp-Source: ADFU+vtoJN5SOz98NJqfaijENWl26HxcF9pZ/8iHhxJ8ELrt2v54pdlzeUIPj7fTBYhA+q01LVCxXg== X-Received: by 2002:a5d:56cd:: with SMTP id m13mr4757951wrw.236.1584630658863; Thu, 19 Mar 2020 08:10:58 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:58 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 13/14] fanotify: record name info for FAN_DIR_MODIFY event Date: Thu, 19 Mar 2020 17:10:21 +0200 Message-Id: <20200319151022.31456-14-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org For FAN_DIR_MODIFY event, allocate a variable size event struct to store the dir entry name along side the directory file handle. At this point, name info reporting is not yet implemented, so trying to set FAN_DIR_MODIFY in mark mask will return -EINVAL. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 72 +++++++++++++++++++++++++++--- fs/notify/fanotify/fanotify.h | 30 ++++++++++++- fs/notify/fanotify/fanotify_user.c | 4 +- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 75f288d5eeab..22e198ab2687 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -53,6 +53,23 @@ static bool fanotify_fid_event_equal(struct fanotify_fid_event *ffe1, fanotify_fh_equal(&ffe1->object_fh, &ffe2->object_fh); } +static bool fanotify_name_event_equal(struct fanotify_name_event *fne1, + struct fanotify_name_event *fne2) +{ + /* + * Do not merge name events without dir fh. + * FAN_DIR_MODIFY does not encode object fh, so it may be empty. + */ + if (!fne1->dir_fh.len) + return false; + + if (fne1->name_len != fne2->name_len || + !fanotify_fh_equal(&fne1->dir_fh, &fne2->dir_fh)) + return false; + + return !memcmp(fne1->name, fne2->name, fne1->name_len); +} + static bool should_merge(struct fsnotify_event *old_fsn, struct fsnotify_event *new_fsn) { @@ -84,6 +101,9 @@ static bool should_merge(struct fsnotify_event *old_fsn, return fanotify_fid_event_equal(FANOTIFY_FE(old), FANOTIFY_FE(new)); + case FANOTIFY_EVENT_TYPE_FID_NAME: + return fanotify_name_event_equal(FANOTIFY_NE(old), + FANOTIFY_NE(new)); default: WARN_ON_ONCE(1); } @@ -320,17 +340,21 @@ static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask, struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, struct inode *inode, u32 mask, const void *data, int data_type, + const struct qstr *file_name, __kernel_fsid_t *fsid) { struct fanotify_event *event = NULL; struct fanotify_fid_event *ffe = NULL; + struct fanotify_name_event *fne = NULL; gfp_t gfp = GFP_KERNEL_ACCOUNT; struct inode *id = fanotify_fid_inode(inode, mask, data, data_type); const struct path *path = fsnotify_data_path(data, data_type); + struct inode *dir = NULL; /* Make sure we can easily cast between inherited structs */ BUILD_BUG_ON(offsetof(struct fanotify_event, fse) != 0); BUILD_BUG_ON(offsetof(struct fanotify_fid_event, fae) != 0); + BUILD_BUG_ON(offsetof(struct fanotify_name_event, fae) != 0); BUILD_BUG_ON(offsetof(struct fanotify_path_event, fae) != 0); BUILD_BUG_ON(offsetof(struct fanotify_perm_event, fae) != 0); @@ -362,6 +386,24 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, goto init; } + /* + * For FAN_DIR_MODIFY event, we report the fid of the directory and + * the name of the modified entry. + * Allocate an fanotify_name_event struct and copy the name. + */ + if (mask & FAN_DIR_MODIFY && !(WARN_ON_ONCE(!file_name))) { + dir = inode; + fne = kmalloc(sizeof(*fne) + file_name->len + 1, gfp); + if (!fne) + goto out; + + event = &fne->fae; + event->type = FANOTIFY_EVENT_TYPE_FID_NAME; + fne->name_len = file_name->len; + strcpy(fne->name, file_name->name); + goto init; + } + if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp); if (!ffe) @@ -377,7 +419,7 @@ struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, event->type = FANOTIFY_EVENT_TYPE_PATH; } -init: __maybe_unused +init: /* * Use the victim inode instead of the watching inode as the id for * event queue, so event reported on parent is merged with event @@ -390,11 +432,19 @@ init: __maybe_unused else event->pid = get_pid(task_tgid(current)); if (fanotify_event_has_fid(event)) { - ffe->object_fh.len = 0; + struct fanotify_fh *obj_fh = fanotify_event_object_fh(event); + if (fsid) - ffe->fsid = *fsid; - if (id) - fanotify_encode_fh(&ffe->object_fh, id, gfp); + *fanotify_event_fsid(event) = *fsid; + if (fne && dir) { + /* The reported name is relative to 'dir' */ + fanotify_encode_fh(&fne->dir_fh, dir, gfp); + } else if (obj_fh) { + if (id) + fanotify_encode_fh(obj_fh, id, gfp); + else + obj_fh->len = 0; + } } else if (fanotify_event_has_path(event)) { struct path *p = fanotify_event_path(event); @@ -503,7 +553,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, } event = fanotify_alloc_event(group, inode, mask, data, data_type, - &fsid); + file_name, &fsid); ret = -ENOMEM; if (unlikely(!event)) { /* @@ -563,6 +613,13 @@ static void fanotify_free_fid_event(struct fanotify_fid_event *ffe) kmem_cache_free(fanotify_fid_event_cachep, ffe); } +static void fanotify_free_name_event(struct fanotify_name_event *fne) +{ + if (fanotify_fh_has_ext_buf(&fne->dir_fh)) + kfree(fanotify_fh_ext_buf(&fne->dir_fh)); + kfree(fne); +} + static void fanotify_free_event(struct fsnotify_event *fsn_event) { struct fanotify_event *event; @@ -579,6 +636,9 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event) case FANOTIFY_EVENT_TYPE_FID: fanotify_free_fid_event(FANOTIFY_FE(event)); break; + case FANOTIFY_EVENT_TYPE_FID_NAME: + fanotify_free_name_event(FANOTIFY_NE(event)); + break; default: WARN_ON_ONCE(1); } diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 1bc73a65d9d2..6648f01f900f 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h @@ -59,7 +59,8 @@ static inline void *fanotify_fh_buf(struct fanotify_fh *fh) * be freed and which concrete struct it may be cast to. */ enum fanotify_event_type { - FANOTIFY_EVENT_TYPE_FID, + FANOTIFY_EVENT_TYPE_FID, /* fixed length */ + FANOTIFY_EVENT_TYPE_FID_NAME, /* variable length */ FANOTIFY_EVENT_TYPE_PATH, FANOTIFY_EVENT_TYPE_PATH_PERM, }; @@ -79,15 +80,28 @@ struct fanotify_fid_event { #define FANOTIFY_FE(event) ((struct fanotify_fid_event *)(event)) +struct fanotify_name_event { + struct fanotify_event fae; + __kernel_fsid_t fsid; + struct fanotify_fh dir_fh; + u8 name_len; + char name[0]; +}; + +#define FANOTIFY_NE(event) ((struct fanotify_name_event *)(event)) + static inline bool fanotify_event_has_fid(struct fanotify_event *event) { - return event->type == FANOTIFY_EVENT_TYPE_FID; + return event->type == FANOTIFY_EVENT_TYPE_FID || + event->type == FANOTIFY_EVENT_TYPE_FID_NAME; } static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event) { if (event->type == FANOTIFY_EVENT_TYPE_FID) return &FANOTIFY_FE(event)->fsid; + else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) + return &FANOTIFY_NE(event)->fsid; else return NULL; } @@ -108,6 +122,17 @@ static inline int fanotify_event_object_fh_len(struct fanotify_event *event) return fh ? fh->len : 0; } +static inline bool fanotify_event_has_name(struct fanotify_event *event) +{ + return event->type == FANOTIFY_EVENT_TYPE_FID_NAME; +} + +static inline int fanotify_event_name_len(struct fanotify_event *event) +{ + return fanotify_event_has_name(event) ? + FANOTIFY_NE(event)->name_len : 0; +} + struct fanotify_path_event { struct fanotify_event fae; struct path path; @@ -166,4 +191,5 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event) struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, struct inode *inode, u32 mask, const void *data, int data_type, + const struct qstr *file_name, __kernel_fsid_t *fsid); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index aaa62bd2b80e..2eff2cfa88ce 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -212,7 +212,7 @@ static int copy_fid_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, struct fanotify_event_info_fid info = { }; struct file_handle handle = { }; unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf; - size_t fh_len = fh->len; + size_t fh_len = fh ? fh->len : 0; size_t len = fanotify_fid_info_len(fh_len); if (!len) @@ -829,7 +829,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) group->memcg = get_mem_cgroup_from_mm(current->mm); oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, - FSNOTIFY_EVENT_NONE, NULL); + FSNOTIFY_EVENT_NONE, NULL, NULL); if (unlikely(!oevent)) { fd = -ENOMEM; goto out_destroy_group; From patchwork Thu Mar 19 15:10:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11447491 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 17C5F913 for ; Thu, 19 Mar 2020 15:11:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E1C6920B1F for ; Thu, 19 Mar 2020 15:11:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UWsIpJBP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727860AbgCSPLD (ORCPT ); Thu, 19 Mar 2020 11:11:03 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:45278 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727788AbgCSPLC (ORCPT ); Thu, 19 Mar 2020 11:11:02 -0400 Received: by mail-wr1-f68.google.com with SMTP id i9so3430993wrx.12 for ; Thu, 19 Mar 2020 08:11:01 -0700 (PDT) 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=q0X/T/ayuQhURy/YnvF8QKmjOUhV9e//GkpfBUDO2lI=; b=UWsIpJBPZVRhKE3GJnj84KapVovoDcLto+cwNJn00SQART9/oiJjsF6eU0zd+O2tmC fM2Ayxvach4QWx0V5If/yM0Dpy61NQmLIfLuhiHnPnQVV6f2hyA4aCH8fAmvxoz00LcO kUY4ScA+gnzxI5dhrCHtO2qgCgdQLt6c8kYJau7ePBRaQfusxHuxJ8Ky66nV4OF6pR9y Wlf16ZgfpB6czywx8/L4SxaSKGo14+iM2oRdvsyjmF4/T0+T/BdJ7odtXinfU3CuUvZ/ zeLW0Nm297kqFUCVHWROLMKuucAtk6YqU/uFPCWg6rBpwZX+RGrtEJGL/uOZH1HM2L8Z zCGA== 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=q0X/T/ayuQhURy/YnvF8QKmjOUhV9e//GkpfBUDO2lI=; b=T/Q1ygGUovbIGTB7pg00FDGtx/bZ/SMBHMKJtzbzdBLYBqBX99iVDVFGAnDgENSy8N IMtUOeX3P1UAF14Ribm+1tSk3ZpFZYs+iI5acuOZleQj2FQNf1+KT9f1Eavi8eVVAa32 KHi/H885YaaATK0Wr3/gdxVSNjBx8J66L+N1FSO9XFb+6VhSyBlO2RplUasctyQLkI+C VyvczJdE6uVaukT2zLrEOd1G9fT8FAYuk2qYJ8hghaffUNePfakIc4UTgECkwytNvOJJ YUccuE9J2Fj2kxP0H0KKeQw2DTqZ9WYXtBDzz56PnKIL1XODqKE0yszupt8O6dVgcncn Hz0w== X-Gm-Message-State: ANhLgQ0ML47y/5Xx5jMzPXfJO+q1a8duUJYnw7+H7ohXLMbOaU+XWTPZ CL97y96EyKBXuL0Q+8h2T2E= X-Google-Smtp-Source: ADFU+vuWjG9Qp3FPzufNExZ51XMThavFoyayRo2i3ipwomZhVCBwcs6DT39FNFIA44WfBBrRHEv2xw== X-Received: by 2002:a5d:5388:: with SMTP id d8mr4685284wrv.270.1584630660388; Thu, 19 Mar 2020 08:11:00 -0700 (PDT) Received: from localhost.localdomain ([141.226.9.174]) by smtp.gmail.com with ESMTPSA id t193sm3716959wmt.14.2020.03.19.08.10.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Mar 2020 08:10:59 -0700 (PDT) From: Amir Goldstein To: Jan Kara Cc: Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v3 14/14] fanotify: report name info for FAN_DIR_MODIFY event Date: Thu, 19 Mar 2020 17:10:22 +0200 Message-Id: <20200319151022.31456-15-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319151022.31456-1-amir73il@gmail.com> References: <20200319151022.31456-1-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Report event FAN_DIR_MODIFY with name in a variable length record similar to how fid's are reported. With name info reporting implemented, setting FAN_DIR_MODIFY in mark mask is now allowed. When events are reported with name, the reported fid identifies the directory and the name follows the fid. The info record type for this event info is FAN_EVENT_INFO_TYPE_DFID_NAME. For now, all reported events have at most one info record which is either FAN_EVENT_INFO_TYPE_FID or FAN_EVENT_INFO_TYPE_DFID_NAME (for FAN_DIR_MODIFY). Later on, events "on child" will report both records. There are several ways that an application can use this information: 1. When watching a single directory, the name is always relative to the watched directory, so application need to fstatat(2) the name relative to the watched directory. 2. When watching a set of directories, the application could keep a map of dirfd for all watched directories and hash the map by fid obtained with name_to_handle_at(2). When getting a name event, the fid in the event info could be used to lookup the base dirfd in the map and then call fstatat(2) with that dirfd. 3. When watching a filesystem (FAN_MARK_FILESYSTEM) or a large set of directories, the application could use open_by_handle_at(2) with the fid in event info to obtain dirfd for the directory where event happened and call fstatat(2) with this dirfd. The last option scales better for a large number of watched directories. The first two options may be available in the future also for non privileged fanotify watchers, because open_by_handle_at(2) requires the CAP_DAC_READ_SEARCH capability. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 2 +- fs/notify/fanotify/fanotify_user.c | 109 +++++++++++++++++++++++------ include/linux/fanotify.h | 3 +- include/uapi/linux/fanotify.h | 1 + 4 files changed, 90 insertions(+), 25 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 22e198ab2687..c07b1891a720 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -526,7 +526,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(FAN_OPEN_EXEC != FS_OPEN_EXEC); BUILD_BUG_ON(FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM); - BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19); + BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 20); mask = fanotify_group_event_mask(group, iter_info, mask, data, data_type); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 2eff2cfa88ce..95256baeb808 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -51,22 +51,35 @@ struct kmem_cache *fanotify_path_event_cachep __read_mostly; struct kmem_cache *fanotify_perm_event_cachep __read_mostly; #define FANOTIFY_EVENT_ALIGN 4 +#define FANOTIFY_INFO_HDR_LEN \ + (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle)) -static int fanotify_fid_info_len(int fh_len) +static int fanotify_fid_info_len(int fh_len, int name_len) { - return roundup(sizeof(struct fanotify_event_info_fid) + - sizeof(struct file_handle) + fh_len, - FANOTIFY_EVENT_ALIGN); + int info_len = fh_len; + + if (name_len) + info_len += name_len + 1; + + return roundup(FANOTIFY_INFO_HDR_LEN + info_len, FANOTIFY_EVENT_ALIGN); } static int fanotify_event_info_len(struct fanotify_event *event) { + int info_len = 0; int fh_len = fanotify_event_object_fh_len(event); - if (!fh_len) - return 0; + if (fh_len) + info_len += fanotify_fid_info_len(fh_len, 0); - return fanotify_fid_info_len(fh_len); + if (fanotify_event_name_len(event)) { + struct fanotify_name_event *fne = FANOTIFY_NE(event); + + info_len += fanotify_fid_info_len(fne->dir_fh.len, + fne->name_len); + } + + return info_len; } /* @@ -206,23 +219,32 @@ static int process_access_response(struct fsnotify_group *group, return -ENOENT; } -static int copy_fid_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, - char __user *buf) +static int copy_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, + const char *name, size_t name_len, + char __user *buf, size_t count) { struct fanotify_event_info_fid info = { }; struct file_handle handle = { }; unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf; size_t fh_len = fh ? fh->len : 0; - size_t len = fanotify_fid_info_len(fh_len); + size_t info_len = fanotify_fid_info_len(fh_len, name_len); + size_t len = info_len; + + pr_debug("%s: fh_len=%zu name_len=%zu, info_len=%zu, count=%zu\n", + __func__, fh_len, name_len, info_len, count); - if (!len) + if (!fh_len || (name && !name_len)) return 0; - if (WARN_ON_ONCE(len < sizeof(info) + sizeof(handle) + fh_len)) + if (WARN_ON_ONCE(len < sizeof(info) || len > count)) return -EFAULT; - /* Copy event info fid header followed by vaiable sized file handle */ - info.hdr.info_type = FAN_EVENT_INFO_TYPE_FID; + /* + * Copy event info fid header followed by variable sized file handle + * and optionally followed by variable sized filename. + */ + info.hdr.info_type = name_len ? FAN_EVENT_INFO_TYPE_DFID_NAME : + FAN_EVENT_INFO_TYPE_FID; info.hdr.len = len; info.fsid = *fsid; if (copy_to_user(buf, &info, sizeof(info))) @@ -230,6 +252,9 @@ static int copy_fid_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, buf += sizeof(info); len -= sizeof(info); + if (WARN_ON_ONCE(len < sizeof(handle))) + return -EFAULT; + handle.handle_type = fh->type; handle.handle_bytes = fh_len; if (copy_to_user(buf, &handle, sizeof(handle))) @@ -237,9 +262,12 @@ static int copy_fid_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, buf += sizeof(handle); len -= sizeof(handle); + if (WARN_ON_ONCE(len < fh_len)) + return -EFAULT; + /* - * For an inline fh, copy through stack to exclude the copy from - * usercopy hardening protections. + * For an inline fh and inline file name, copy through stack to exclude + * the copy from usercopy hardening protections. */ fh_buf = fanotify_fh_buf(fh); if (fh_len <= FANOTIFY_INLINE_FH_LEN) { @@ -249,14 +277,28 @@ static int copy_fid_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, if (copy_to_user(buf, fh_buf, fh_len)) return -EFAULT; - /* Pad with 0's */ buf += fh_len; len -= fh_len; + + if (name_len) { + /* Copy the filename with terminating null */ + name_len++; + if (WARN_ON_ONCE(len < name_len)) + return -EFAULT; + + if (copy_to_user(buf, name, name_len)) + return -EFAULT; + + buf += name_len; + len -= name_len; + } + + /* Pad with 0's */ WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN); if (len > 0 && clear_user(buf, len)) return -EFAULT; - return 0; + return info_len; } static ssize_t copy_event_to_user(struct fsnotify_group *group, @@ -298,17 +340,38 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN)) goto out_close_fd; + buf += FAN_EVENT_METADATA_LEN; + count -= FAN_EVENT_METADATA_LEN; + if (fanotify_is_perm_event(event->mask)) FANOTIFY_PERM(fsn_event)->fd = fd; - if (f) { + if (f) fd_install(fd, f); - } else if (fanotify_event_has_fid(event)) { - ret = copy_fid_to_user(fanotify_event_fsid(event), - fanotify_event_object_fh(event), - buf + FAN_EVENT_METADATA_LEN); + + /* Event info records order is: dir fid + name, child fid */ + if (fanotify_event_name_len(event)) { + struct fanotify_name_event *fne = FANOTIFY_NE(event); + + ret = copy_info_to_user(fanotify_event_fsid(event), + &fne->dir_fh, fne->name, fne->name_len, + buf, count); if (ret < 0) return ret; + + buf += ret; + count -= ret; + } + + if (fanotify_event_object_fh_len(event)) { + ret = copy_info_to_user(fanotify_event_fsid(event), + fanotify_event_object_fh(event), + NULL, 0, buf, count); + if (ret < 0) + return ret; + + buf += ret; + count -= ret; } return metadata.event_len; diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index b79fa9bb7359..3049a6c06d9e 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -47,7 +47,8 @@ * Directory entry modification events - reported only to directory * where entry is modified and not to a watching parent. */ -#define FANOTIFY_DIRENT_EVENTS (FAN_MOVE | FAN_CREATE | FAN_DELETE) +#define FANOTIFY_DIRENT_EVENTS (FAN_MOVE | FAN_CREATE | FAN_DELETE | \ + FAN_DIR_MODIFY) /* Events that can only be reported with data type FSNOTIFY_EVENT_INODE */ #define FANOTIFY_INODE_EVENTS (FANOTIFY_DIRENT_EVENTS | \ diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index 615fa2c87179..2b56e194b858 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h @@ -117,6 +117,7 @@ struct fanotify_event_metadata { }; #define FAN_EVENT_INFO_TYPE_FID 1 +#define FAN_EVENT_INFO_TYPE_DFID_NAME 2 /* Variable length info record following event metadata */ struct fanotify_event_info_header {