From patchwork Thu Nov 21 11:22:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kara X-Patchwork-Id: 13881880 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 89067D6ED0A for ; Thu, 21 Nov 2024 11:23:03 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id AB7546B009F; Thu, 21 Nov 2024 06:22:32 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 9C71E6B00A4; Thu, 21 Nov 2024 06:22:32 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 29E5F6B009F; Thu, 21 Nov 2024 06:22:32 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id BEE456B009D for ; Thu, 21 Nov 2024 06:22:31 -0500 (EST) Received: from smtpin29.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 8027EC1303 for ; Thu, 21 Nov 2024 11:22:31 +0000 (UTC) X-FDA: 82809863598.29.8DEE90D Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) by imf02.hostedemail.com (Postfix) with ESMTP id 8761980017 for ; Thu, 21 Nov 2024 11:20:49 +0000 (UTC) Authentication-Results: imf02.hostedemail.com; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=pzPiHSSo; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b="ySVK/qoK"; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=pzPiHSSo; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b="ySVK/qoK"; dmarc=none; spf=pass (imf02.hostedemail.com: domain of jack@suse.cz designates 195.135.223.131 as permitted sender) smtp.mailfrom=jack@suse.cz ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1732188013; a=rsa-sha256; cv=none; b=ALOL+6aUByS/cZ1nSfUJwVNyCjeOKkjhvsk6moDAyz0+5HKZiFDC0X7PO465zIj0fgKQYP DaA5h0IF7hQpTmuvTGEYPvQ/IcIG91f1tVEw4OUuw/jOqFOcvLatSEZ2Z0q5lQifUPwmoP PJyLJDy4s4+hdhZVGfStF9Yyq8tIvjU= ARC-Authentication-Results: i=1; imf02.hostedemail.com; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=pzPiHSSo; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b="ySVK/qoK"; dkim=pass header.d=suse.cz header.s=susede2_rsa header.b=pzPiHSSo; dkim=pass header.d=suse.cz header.s=susede2_ed25519 header.b="ySVK/qoK"; dmarc=none; spf=pass (imf02.hostedemail.com: domain of jack@suse.cz designates 195.135.223.131 as permitted sender) smtp.mailfrom=jack@suse.cz ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1732188013; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=WuIrTjlD7giJFMek9Z6w/1QoxLAn4PO/HWcQhy0un38=; b=36WR6ZiXtLYQUNz5EFmvVan8DWqMHCG+DGSfB1XRH/SJkmAicC5fG37l5NLaIE3lp/SnJW qX6+v7AbHYyh2pRzojAaAPYCmxJSfonRnLxVSV9MOLZ+lbra3pC0NRgZvjY0rTMWspCAh0 4cW8VVSZ0NsgHCJ7nLIwrvZ07Ns6xXA= Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 99BF21F800; Thu, 21 Nov 2024 11:22:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1732188144; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WuIrTjlD7giJFMek9Z6w/1QoxLAn4PO/HWcQhy0un38=; b=pzPiHSSoj4yXZITU9FzzG/TOnecS2AiHaoo+LmjlLuTmpYZoOPEJsreboE8wZElOAuyQiO CkwWqoOOCFq19p8/96z7OXvZgDWI2cirJQfSsNBE0RF7577iQ4JBaO5A1cnVLunCITcCQr 3gBKj959vZLmDotAFMDtD8APrBvQQMk= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1732188144; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WuIrTjlD7giJFMek9Z6w/1QoxLAn4PO/HWcQhy0un38=; b=ySVK/qoKjU5kW7y5SOLCqSnSJHUHG4yAd93e0OgJc9Etp96qL95NEO+j8rBkRd9VeVXMlx NH1tzEKardeXVDBQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1732188144; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WuIrTjlD7giJFMek9Z6w/1QoxLAn4PO/HWcQhy0un38=; b=pzPiHSSoj4yXZITU9FzzG/TOnecS2AiHaoo+LmjlLuTmpYZoOPEJsreboE8wZElOAuyQiO CkwWqoOOCFq19p8/96z7OXvZgDWI2cirJQfSsNBE0RF7577iQ4JBaO5A1cnVLunCITcCQr 3gBKj959vZLmDotAFMDtD8APrBvQQMk= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1732188144; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WuIrTjlD7giJFMek9Z6w/1QoxLAn4PO/HWcQhy0un38=; b=ySVK/qoKjU5kW7y5SOLCqSnSJHUHG4yAd93e0OgJc9Etp96qL95NEO+j8rBkRd9VeVXMlx NH1tzEKardeXVDBQ== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 8CCF913ACE; Thu, 21 Nov 2024 11:22:24 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id aVFGIvAXP2c+fwAAD6G6ig (envelope-from ); Thu, 21 Nov 2024 11:22:24 +0000 Received: by quack3.suse.cz (Postfix, from userid 1000) id 2C652A08A2; Thu, 21 Nov 2024 12:22:24 +0100 (CET) From: Jan Kara To: Cc: Amir Goldstein , Josef Bacik , brauner@kernel.org, Linus Torvalds , Al Viro , linux-xfs@vger.kernel.org, linux-btrfs@vger.kernel.org, linux-ext4@vger.kernel.org, linux-mm@kvack.org, Jan Kara Subject: [PATCH 12/19] fanotify: allow to set errno in FAN_DENY permission response Date: Thu, 21 Nov 2024 12:22:11 +0100 Message-Id: <20241121112218.8249-13-jack@suse.cz> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20241121112218.8249-1-jack@suse.cz> References: <20241121112218.8249-1-jack@suse.cz> MIME-Version: 1.0 X-Rspamd-Queue-Id: 8761980017 X-Stat-Signature: ynqp141jqjw3nhcz1kecc95yi73f1xin X-Rspam-User: X-Rspamd-Server: rspam05 X-HE-Tag: 1732188049-637805 X-HE-Meta: U2FsdGVkX1/1t94SfUBiSyULIJH4XDX1xY4wgOQ5+Sbh8xlnBK4IkMZAZTJaNsBQ8NxikYyAvY7jHPk1cQ0uO7GX2o6yWNDTF8TirORoz+KCJABteZ664RFLfcMfYRb3EMriIY7kjDZ3otMu5FFLiuIVpoEZh7pEjrmwk5r6tiWV+9DQkvh4khWRLFB4QMjezM9yJexZheZPy+MVBfEh0zjmtnNbtDrwtaheqMYomojZBNjPfNO7XLjG7xE68duwYEzDJ9bwPw09t+0gB0nvpCn1on4nNChgIJ/lFcwvEOLNmhx8NMQuR2D1y2GRfvR1Ip+jHhp8QMhejCcwxHkjayBSDWD5IAFeWDiclxH2O2AyWRGDlJJPWKfyBKG06sYX2O4/oMBiYDfaF6pg1WyDysNocfEqQKnFV5P2TGXD98h/dD1frtXx0f1c+5IuqDUwV3khyGw+0PCO2HUMfBdHMJOTKE6MJf4IT2GrOQ8AWYG99NYawwch1ORhuCo/b2f7KOR9B3pltg4OqoGJnw2cO9Nn+pKx/x3t2fE9IGKEpVHmQXX2XHCKqn9CtJhCzCa1+WcTjlVwN4MYc+hLNawReuihI2Dry6jo9pGHW/geVEICBqnVviAgTjWvfFpWY9palIogCxXMwqPKrEG8Azsz1IHx3d6TSmlB6qyKbWp014EBIiWkLiXr55/h7xkBbzLY6FBhPkePlzZ7zLMt5zrMf8w7M6Yb9WCzZD/ZDr3Fqf3a48celVYYj87F5MjhT4iFDeKrytgrs8krPauKx4Dgt8tYL79kR0Nl05ZTB7vY7vm5XJhcuyux+s/T/2ib3XG/AI0IITSpULVZkFBWZ0zPDCNIEIvgFUup0sG0SXFG4haA/S3HG4KKvDo1obOxFOT4osqHlSkRfkQM7/ZGQ+F7fQe+3uapEk8q6JEflG+LdM+8+owLrDRxgCgSVI63c7e4CaZ5PIlqOTlCInxhlgb ZIrsu7T+ CKF2aLlKnkvHQtrFME7PDVLgHHeDHqy4drFccSG/gRi1o2YTzgMtxSLFGhZvzQq80pPIgWRUbhhuYI5PQqibTeW2wkAWctQNnyCIeIeltzSLSJwL8NpYiRfgwJD2npkKqTRBeYtpiZuS+GaTZVckljQjx+AYErwZraikjalhmOklklbtWum8MFSwkLLPe7cEhoJKqKvbWfvAfnbhHOWnqHJxKnOaivv/BzbKxSAEJYReQEcE233BFNO5zYUm9pVeYlndQ+nq/aLR5QU6hJFpUkIxykd/+CbQwIV9sC57NpcxSbiyUwQJv4w5r7jj5Zy3ihPHkSX9NMwExyfWt48ZuHYifNvouLpoTQYR62IgZuA58GsYA7l8LqmKXwMm82j4wBCiYZHDXtJEnUf5tKaXECOgPOYaYG/9m6tHPifd2diTHDn052lQs6VBVI+W244PeJXAauUbQmP9FqT4= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Amir Goldstein With FAN_DENY response, user trying to perform the filesystem operation gets an error with errno set to EPERM. It is useful for hierarchical storage management (HSM) service to be able to deny access for reasons more diverse than EPERM, for example EAGAIN, if HSM could retry the operation later. Allow fanotify groups with priority FAN_CLASSS_PRE_CONTENT to responsd to permission events with the response value FAN_DENY_ERRNO(errno), instead of FAN_DENY to return a custom error. Limit custom error values to errors expected on read(2)/write(2) and open(2) of regular files. This list could be extended in the future. Userspace can test for legitimate values of FAN_DENY_ERRNO(errno) by writing a response to an fanotify group fd with a value of FAN_NOFD in the fd field of the response. The change in fanotify_response is backward compatible, because errno is written in the high 8 bits of the 32bit response field and old kernels reject respose value with high bits set. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Link: https://patch.msgid.link/1e5fb6af84b69ca96b5c849fa5f10bdf4d1dc414.1731684329.git.josef@toxicpanda.com --- fs/notify/fanotify/fanotify.c | 17 +++++++++++++---- fs/notify/fanotify/fanotify.h | 5 +++++ fs/notify/fanotify/fanotify_user.c | 29 +++++++++++++++++++++++++++-- include/linux/fanotify.h | 4 +++- include/uapi/linux/fanotify.h | 7 +++++++ 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 5e05410ddb9f..6ebe95e5bbdd 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -224,7 +224,7 @@ static int fanotify_get_response(struct fsnotify_group *group, struct fanotify_perm_event *event, struct fsnotify_iter_info *iter_info) { - int ret; + int ret, errno; pr_debug("%s: group=%p event=%p\n", __func__, group, event); @@ -263,14 +263,23 @@ static int fanotify_get_response(struct fsnotify_group *group, ret = 0; break; case FAN_DENY: + /* Check custom errno from pre-content events */ + errno = fanotify_get_response_errno(event->response); + if (errno) { + ret = -errno; + break; + } + fallthrough; default: ret = -EPERM; } /* Check if the response should be audited */ - if (event->response & FAN_AUDIT) - audit_fanotify(event->response & ~FAN_AUDIT, - &event->audit_rule); + if (event->response & FAN_AUDIT) { + u32 response = event->response & + (FANOTIFY_RESPONSE_ACCESS | FANOTIFY_RESPONSE_FLAGS); + audit_fanotify(response & ~FAN_AUDIT, &event->audit_rule); + } pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__, group, event, ret); diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 7f06355afa1f..c12cbc270539 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h @@ -528,3 +528,8 @@ static inline unsigned int fanotify_mark_user_flags(struct fsnotify_mark *mark) return mflags; } + +static inline u32 fanotify_get_response_errno(int res) +{ + return (res >> FAN_ERRNO_SHIFT) & FAN_ERRNO_MASK; +} diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 61e0f67169e4..0919ea735f4a 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -328,11 +328,12 @@ static int process_access_response(struct fsnotify_group *group, struct fanotify_perm_event *event; int fd = response_struct->fd; u32 response = response_struct->response; + int errno = fanotify_get_response_errno(response); int ret = info_len; struct fanotify_response_info_audit_rule friar; - pr_debug("%s: group=%p fd=%d response=%u buf=%p size=%zu\n", __func__, - group, fd, response, info, info_len); + pr_debug("%s: group=%p fd=%d response=%x errno=%d buf=%p size=%zu\n", + __func__, group, fd, response, errno, info, info_len); /* * make sure the response is valid, if invalid we do nothing and either * userspace can send a valid response or we will clean it up after the @@ -343,7 +344,31 @@ static int process_access_response(struct fsnotify_group *group, switch (response & FANOTIFY_RESPONSE_ACCESS) { case FAN_ALLOW: + if (errno) + return -EINVAL; + break; case FAN_DENY: + /* Custom errno is supported only for pre-content groups */ + if (errno && group->priority != FSNOTIFY_PRIO_PRE_CONTENT) + return -EINVAL; + + /* + * Limit errno to values expected on open(2)/read(2)/write(2) + * of regular files. + */ + switch (errno) { + case 0: + case EIO: + case EPERM: + case EBUSY: + case ETXTBSY: + case EAGAIN: + case ENOSPC: + case EDQUOT: + break; + default: + return -EINVAL; + } break; default: return -EINVAL; diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index c747af064d2c..78f660ebc318 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -132,7 +132,9 @@ /* These masks check for invalid bits in permission responses. */ #define FANOTIFY_RESPONSE_ACCESS (FAN_ALLOW | FAN_DENY) #define FANOTIFY_RESPONSE_FLAGS (FAN_AUDIT | FAN_INFO) -#define FANOTIFY_RESPONSE_VALID_MASK (FANOTIFY_RESPONSE_ACCESS | FANOTIFY_RESPONSE_FLAGS) +#define FANOTIFY_RESPONSE_VALID_MASK \ + (FANOTIFY_RESPONSE_ACCESS | FANOTIFY_RESPONSE_FLAGS | \ + (FAN_ERRNO_MASK << FAN_ERRNO_SHIFT)) /* Do not use these old uapi constants internally */ #undef FAN_ALL_CLASS_BITS diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index 0636a9c85dd0..bd8167979707 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h @@ -235,6 +235,13 @@ struct fanotify_response_info_audit_rule { /* Legit userspace responses to a _PERM event */ #define FAN_ALLOW 0x01 #define FAN_DENY 0x02 +/* errno other than EPERM can specified in upper byte of deny response */ +#define FAN_ERRNO_BITS 8 +#define FAN_ERRNO_SHIFT (32 - FAN_ERRNO_BITS) +#define FAN_ERRNO_MASK ((1 << FAN_ERRNO_BITS) - 1) +#define FAN_DENY_ERRNO(err) \ + (FAN_DENY | ((((__u32)(err)) & FAN_ERRNO_MASK) << FAN_ERRNO_SHIFT)) + #define FAN_AUDIT 0x10 /* Bitmask to create audit record for result */ #define FAN_INFO 0x20 /* Bitmask to indicate additional information */