From patchwork Fri Nov 15 15:30:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13876449 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 7A7A5D68BC6 for ; Fri, 15 Nov 2024 15:31:59 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7FD8B6B009E; Fri, 15 Nov 2024 10:31:45 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 7AEF06B009F; Fri, 15 Nov 2024 10:31:45 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 562F46B00A0; Fri, 15 Nov 2024 10:31:45 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 3BB4E6B009E for ; Fri, 15 Nov 2024 10:31:45 -0500 (EST) Received: from smtpin10.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id E8A50817FF for ; Fri, 15 Nov 2024 15:31:44 +0000 (UTC) X-FDA: 82788717900.10.3B40DD8 Received: from mail-yb1-f170.google.com (mail-yb1-f170.google.com [209.85.219.170]) by imf04.hostedemail.com (Postfix) with ESMTP id 601E64000A for ; Fri, 15 Nov 2024 15:30:45 +0000 (UTC) Authentication-Results: imf04.hostedemail.com; dkim=pass header.d=toxicpanda-com.20230601.gappssmtp.com header.s=20230601 header.b=WRJ1ae7w; spf=none (imf04.hostedemail.com: domain of josef@toxicpanda.com has no SPF policy when checking 209.85.219.170) smtp.mailfrom=josef@toxicpanda.com; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1731684613; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=oYVz+XyZ9SoqwtPGIrYcB7tf/DoyF2fJkEf/z8ZauDI=; b=n7TDwe9URxbTd9wr0tKz1zU59ptEOwljn+je0BVAnOK7LOM05FPzA6ItxXOQGfS9O+2Wvn JtprBAZOEYCxX4d1qSRa8fm1ja5jfYTVQXHRou2EHhTh5Hh8OjczEp29d/bRl1Re96LGus ugh1UPVYX/nnHyO/tXwMxVZdPb4h4x4= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1731684613; a=rsa-sha256; cv=none; b=UXM2w5UuCGOOzavKts5MYeYXiMn121YyPpF7co+9ZhR1Fs58PjSzrN2T7s8L5T42QyrknQ cw9uhvB/I+xF6Tf8IS3yLpA/yVhAyKt/l/9jtJyFfoqjmVRSN3LRExqa88v1tka4bBuCS2 hZrHdBLk3Cd4i1GRn2kXaW7aB5cFnuw= ARC-Authentication-Results: i=1; imf04.hostedemail.com; dkim=pass header.d=toxicpanda-com.20230601.gappssmtp.com header.s=20230601 header.b=WRJ1ae7w; spf=none (imf04.hostedemail.com: domain of josef@toxicpanda.com has no SPF policy when checking 209.85.219.170) smtp.mailfrom=josef@toxicpanda.com; dmarc=none Received: by mail-yb1-f170.google.com with SMTP id 3f1490d57ef6-e380d1389a1so747038276.2 for ; Fri, 15 Nov 2024 07:31:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1731684702; x=1732289502; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=oYVz+XyZ9SoqwtPGIrYcB7tf/DoyF2fJkEf/z8ZauDI=; b=WRJ1ae7wjRyZgPZb9p8FveKjJSCOHMVSezi8vp8JLlA4L2Y5aC+77o4HkN0CIOpzZ8 mFcG8jWmr2Sr3INPMKPY91HnUURK6Iwfl0tPUf1WhVVsDqvytnLJy9Yp/sySZEAbAhUe Fqj1MmC/BEsE4loz5Qt8lgOtUV/2hZ1VJtzfygbvRz3McRhGsYFFTK9fNr/b1rKiZ+Kn 8ctuXNaxETOUlMTwKbatyKuI+o39YAxyANlln8oUXkXBlZ69eSac7E+6PnUJqc4mJTaj FMynNSaMcKVWyxx65Wgq7z8pN6TgYKWSht8n2A4200wzZGQBvaHy61ZT/CIUA3zyt7LI 3KkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731684702; x=1732289502; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oYVz+XyZ9SoqwtPGIrYcB7tf/DoyF2fJkEf/z8ZauDI=; b=SRXCTyp73xIiAwQA6jdbe6Nyn1nd4fuFvawXB6Pwg5CdnsPQP47tu6nGF1A9PfyLqX EI9nyb1/VeS92NAgXYzXMozF43a6eG3b7ShnGKz53DYR3UvQtebiq9MvwDYNF/nZDN9M CfeavfPlGPkaZoD8CnzmG1/4j7cEOEswZpbt7k9sHcOWpkh4dpB2D/LkRYsFbfHjVDee ckMg0qiYUM4Oz5NwoVa9V5D3BinTUTsoOZWKrQ8kSnOJyzr/I7X6Q6/AIRHNPsWxuVfm HjZLHT/s+eVjgKTfrYpGmS2G0IYfw5zVW5e+cXKR0BRIWkI6y3KL97sQX92naVrnJzUC MoyA== X-Forwarded-Encrypted: i=1; AJvYcCUQquANjyZC7Sn8YGRd4rx65m5Tje/mBFZIN1JvCZOKfIg0mzqmD3FD3PfXsM5PccYFd1fr2Z2EmA==@kvack.org X-Gm-Message-State: AOJu0YwV54qC6ykrHSnDLnWEOhBEuuJIgBBXWiS1SVc2aaybNImepPeB /MSPXitSA7o6kGpEfBcmQSW4HqSpzu8tcNHXsxP03CHP2kGOEULMFJiF7U25GcI= X-Google-Smtp-Source: AGHT+IFoxy1YCQFnRgPtGkTRCMBhBl4Fu3YB1s0FmhMUuPf3HGnEc2HjxOuL+DFHWmE6fl1W/EqzGQ== X-Received: by 2002:a05:690c:603:b0:6ee:3c22:cc67 with SMTP id 00721157ae682-6ee558ca435mr38407687b3.0.1731684701510; Fri, 15 Nov 2024 07:31:41 -0800 (PST) Received: from localhost (syn-076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 00721157ae682-6ee440737bcsm7797587b3.61.2024.11.15.07.31.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 07:31:40 -0800 (PST) From: Josef Bacik To: kernel-team@fb.com, linux-fsdevel@vger.kernel.org, jack@suse.cz, amir73il@gmail.com, brauner@kernel.org, torvalds@linux-foundation.org, viro@zeniv.linux.org.uk, linux-xfs@vger.kernel.org, linux-btrfs@vger.kernel.org, linux-mm@kvack.org, linux-ext4@vger.kernel.org Subject: [PATCH v8 12/19] fanotify: allow to set errno in FAN_DENY permission response Date: Fri, 15 Nov 2024 10:30:25 -0500 Message-ID: <1e5fb6af84b69ca96b5c849fa5f10bdf4d1dc414.1731684329.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Server: rspam10 X-Stat-Signature: x5p5tynw7exg7bcoact6pfib31k67w6w X-Rspamd-Queue-Id: 601E64000A X-Rspam-User: X-HE-Tag: 1731684645-729360 X-HE-Meta: U2FsdGVkX1+si5vOBSXyqiBazenNOxhigQKRuYFyqiC132+NQGhzu4ySXZiBkm879vQugXvEA2ADNOrF5atdJy7hE5/OyPwxd0zjHgDlAeo8snvfIGe2WntV3mVDFJMthuVpLKxGGA6pS+yVvFwOtzI54zJdn+WDZ1rpmVASJOpwWtgh8FkCK3wd5qd4aJPHLvnK0DhLM4sZxodyctQkfK2KrEraeixpx0UfXYitfPZJZk1FEdWMSqrRXXG17pEvtBE0rFzwLXUI7TZfF78XIgcqIym/Y42XhGc/ab1StT2odtHpDqWye1EgIxsf2Y6PGgNu1R56XrAR8u7Fez+sBK2A/nhGZEkqSKAi0AYnrpea+0hS56l8qvWAMNnQzhnLQed3N87ihWueTuW+zHAN1UI6W3lpY2N1EJdUPxeK8BcPKv44GyaGM34UwMomfZG+AGOOv9iIuNlyHWj/JceAbEjc3XLmbihS1dA3v4uqob7YsUlmQ29FHFYTGrPZKeyxGb2oVTR4eazLxzJn0C4rIusKMaelfYqwp412JI2BB4Orb+URHbs02kmfSTu+e94HRsegJlm4diTUz5aBO7XkjUotuDUrBEu4f+4tAjV1b1a8b/GEm9XpcGFg1h/RKV7D7uCSDnukEEMZGdhCIrLW/L7tqEOMFKB2YWAq/fYtPCnpoKTAgHcjI19+OKb1pCZ5A2ekG1RzexVWfIMkkdMOgAidjzgm1CnL18lRbasI/LxJH4njiLNpCZo47Mu5Rj0OuCSkp1DEBrCCAPvf3O8y9nF5+XXZwZK69eyiLwKjIfUMmY+IpJJOXcLcyhAaK6y/9MdNv2AVvL6H7O77V+IuTBEtYsqXNQKgTKsAWFc/kMRvewgdiGX1piNyvkgB0FCOwfiNpDzIqvacNAY69Iiovgvu3ro4VxrnNQi9/SjdJrxmXUNu9Hb+BegbntHGTLdOdQH2GNxPQQmsiE1fq3s FIvGZ2Qx ReQwUCrvlMMknld21dBwemUW6IJ24lPcKb5TxOGVEYbId/NqWR12JqqgpJ+nFx4pwwhMbIr4Ssxy0TeV0yUGXBe6+hOdkrRhj1gAqc+xzX/SM4nNvWpUSRTbtLefcY34lQ78LkupdNPVnch319Xvq87cUNrEZ34yBnfL01KM5JD4qMUiGp77757R0vrc/EiNYXU8BPhHY+YW2hAsPD6NHrnJyDa8L1vsLhTjMluLkkyPlEMS1OUtXBssgWmxlmZ4IKeUXt6KnMKHk/XZmqDp970M0GYM6J4XR6bFswebLEOSYV65fN833B1VnfcuT91e58LRd6DSMYxq/2TgYyxfPtBtsE/nuEwsQHi+jb8xqy9+wXG4KoGbD9lR0a2v9u/bo/rjVO8cR+Dv0NIBVJrI/0GL8Mg5oslG8i9V76ir6xT8Gd3m01fM4rU8LYrB9/XCL24gjhL0iMAZGJsPW5ff89w6rXUQwlwRxwI5nbevpEd8CN5oZn0VScWK/zQ== 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 --- fs/notify/fanotify/fanotify.c | 19 +++++++++++---- fs/notify/fanotify/fanotify.h | 5 ++++ fs/notify/fanotify/fanotify_user.c | 37 ++++++++++++++++++++++++++---- include/linux/fanotify.h | 5 +++- include/uapi/linux/fanotify.h | 7 ++++++ 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index da6c3c1c7edf..e3d04d77caba 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -223,7 +223,8 @@ 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; + u32 decision; pr_debug("%s: group=%p event=%p\n", __func__, group, event); @@ -256,20 +257,28 @@ static int fanotify_get_response(struct fsnotify_group *group, goto out; } + decision = event->response & + (FANOTIFY_RESPONSE_ACCESS | FANOTIFY_RESPONSE_FLAGS); /* userspace responded, convert to something usable */ - switch (event->response & FANOTIFY_RESPONSE_ACCESS) { + switch (decision & FANOTIFY_RESPONSE_ACCESS) { case FAN_ALLOW: 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 (decision & FAN_AUDIT) + audit_fanotify(decision & ~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..9e93aba210c9 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; +} diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index c7938d9e8101..28aac467c7e2 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -327,11 +327,14 @@ static int process_access_response(struct fsnotify_group *group, struct fanotify_perm_event *event; int fd = response_struct->fd; u32 response = response_struct->response; + u32 decision = response & + (FANOTIFY_RESPONSE_ACCESS | FANOTIFY_RESPONSE_FLAGS); + 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 @@ -340,18 +343,42 @@ static int process_access_response(struct fsnotify_group *group, if (response & ~FANOTIFY_RESPONSE_VALID_MASK) return -EINVAL; - switch (response & FANOTIFY_RESPONSE_ACCESS) { + switch (decision & 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; } - if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT)) + if ((decision & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT)) return -EINVAL; - if (response & FAN_INFO) { + if (decision & FAN_INFO) { ret = process_access_response_info(info, info_len, &friar); if (ret < 0) return ret; diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index c747af064d2c..d9bb48976b53 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -132,7 +132,10 @@ /* 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_ERRNO (FAN_ERRNO_MASK << FAN_ERRNO_SHIFT) +#define FANOTIFY_RESPONSE_VALID_MASK \ + (FANOTIFY_RESPONSE_ACCESS | FANOTIFY_RESPONSE_FLAGS | \ + FANOTIFY_RESPONSE_ERRNO) /* 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 */