From patchwork Wed Mar 6 07:39:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583435 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB2FE5C91C for ; Wed, 6 Mar 2024 07:39:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710770; cv=none; b=pskZjw/BWe0yFq/+zkaxDqsWf174r6HfNUBSx5KDc220EQ6wg00ahiH6R4ZWVHkDJlplkheXFRIdsWMGZpcBfpAMx7R8I+QZXgRBWaX7Tpbl7owWQoT2GqByyqTXydDZsIkLr4Y+oRczY7xH2jV5YvGf+XQ0y4d1E59HULekLlg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710770; c=relaxed/simple; bh=T9wyGNUK/a5+R+4NnNzOvivl3qko5cvFamHSS6BHobU=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=NoSA460n8B7d8k6YBWqSnPwcx7aOaAXljzRtFCsxRfbb55O3wKGb3o+WMgyrmpPFHtIQ8WrdSxlsBWzs4cK1UuUVHdPxc9ekKAbMw9M2oM16jfLFQn5sT6uGoEXDaEcHosbwbO6cgylnn5pgS+p/D+9IHjWuAqZvL4jRJ9X0WVE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=IYX5Z56s; arc=none smtp.client-ip=209.85.218.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="IYX5Z56s" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-a45bdf6e9c2so23106766b.0 for ; Tue, 05 Mar 2024 23:39:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710767; x=1710315567; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=lKGhvub9+e8WLvaTITikZYN5QDAVXk4MiuBB9Y8ZHfM=; b=IYX5Z56sfNrUJZr1SUPtzFsaooQEAajkLF8knX6XCC7O3AyNfVORM4+v0GqpY57v34 b5K8M5hjbpKFB2Os9joZJnV5EQgeX8T9nNU7WHFCxZx1Jnq0Gy1v+8V6WWIQaNvklrIy 7O9JceoMuctbxkhzkkJ5PzRhd54YOIDR8aMz9QmLMOOPm9o/YbbbQXNsxdUbt6UCu4lO tZGVafEa/BA9pgPLOKjprlqc2zAjkX685oEWZeOSiwn2kE3kTrNZdQbYXUxrjhFVYZib tOG58K0xG2OO870EVgtYdeujJHcyscV5HMvHdRiw2KvOYBzMDX4YOdmLBqKEHBfMX1p2 OxCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710767; x=1710315567; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=lKGhvub9+e8WLvaTITikZYN5QDAVXk4MiuBB9Y8ZHfM=; b=fTorZK2hL2VoXY2TOHRo5DZRuzT9m3m7GZr32YykjBDO3d0I+Ctn+UmvGvowzxYoXH LU7t+A2jFvplN4ryNNX4dR8/hhaC6pitoM8JfS49rwGmROdMYef11Dh7qETOYpJ1i10B dIHFiMz77gmrxED5KB/IfVF4wV61vmN1m3iKZiN8mkdsjAoWYMjw2m+FRXOoS9i2zYNr yKGh7OwJ51QnQVF9vfCAxlA1DACwY4r2EkaqV8nnAWsSr9x3Kp9Ort8mN8i8F0TdMipz ynODx3L4KU7VlSWTjIPXqyfghj0N1xhR7DKDBPbfd+7rZZNaz5g8n0QpZ09yXvW3PES0 iq7w== X-Gm-Message-State: AOJu0Yzr9LMcejLS3oyPtTunYa+oNChjFUWLIY2xKOFBMaY15UDCccW6 11YLDbMSbUGCwQ4mMm/K/7Vt72ABbUDAdNTBQ7rPColaQKk+puK604aDqmIfYXhCXDao6rZMLtw rYA== X-Google-Smtp-Source: AGHT+IFucscsSNmNlMP+XPI0+EFS5ODgbdCNT788DnByzIdHvN/V1lhu7I+wjq6DDchyuikxQvNcYg== X-Received: by 2002:a17:906:4888:b0:a45:b1cf:42f6 with SMTP id v8-20020a170906488800b00a45b1cf42f6mr1523135ejq.9.1709710766566; Tue, 05 Mar 2024 23:39:26 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id wk16-20020a170907055000b00a4532d289edsm3429198ejb.116.2024.03.05.23.39.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:39:26 -0800 (PST) Date: Wed, 6 Mar 2024 07:39:22 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 1/9] bpf: rename fs_kfunc_set_ids to lsm_kfunc_set_ids Message-ID: <18b6eeea5fa3db45a7a3faba0066b5635e998585.1709675979.git.mattbobrowski@google.com> References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net fs_kfunc_set_ids is rather specific to a single BPF kfunc at the moment. Rename it to something a little more generic such that other future BPF kfuncs that are also restricted to BPF LSM program types can reside in the same btf_kfunc_id_set and make use of the same btf_kfunc_filter_t. Signed-off-by: Matt Bobrowski --- kernel/trace/bpf_trace.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 241ddf5e3895..f639663ac339 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1435,7 +1435,7 @@ static int __init bpf_key_sig_kfuncs_init(void) late_initcall(bpf_key_sig_kfuncs_init); #endif /* CONFIG_KEYS */ -/* filesystem kfuncs */ +/* A set of kfuncs that may only be called from BPF LSM program types. */ __bpf_kfunc_start_defs(); /** @@ -1475,31 +1475,33 @@ __bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str, __bpf_kfunc_end_defs(); -BTF_KFUNCS_START(fs_kfunc_set_ids) +BTF_KFUNCS_START(lsm_kfunc_set_ids) BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) -BTF_KFUNCS_END(fs_kfunc_set_ids) +BTF_KFUNCS_END(lsm_kfunc_set_ids) -static int bpf_get_file_xattr_filter(const struct bpf_prog *prog, u32 kfunc_id) +static int bpf_lsm_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id) { - if (!btf_id_set8_contains(&fs_kfunc_set_ids, kfunc_id)) + if (!btf_id_set8_contains(&lsm_kfunc_set_ids, kfunc_id)) return 0; - /* Only allow to attach from LSM hooks, to avoid recursion */ + /* To avoid recursion, only permit kfuncs included within + * lsm_kfunc_set_ids to be called from BPF LSM program types. + */ return prog->type != BPF_PROG_TYPE_LSM ? -EACCES : 0; } -static const struct btf_kfunc_id_set bpf_fs_kfunc_set = { +static const struct btf_kfunc_id_set bpf_lsm_kfunc_set = { .owner = THIS_MODULE, - .set = &fs_kfunc_set_ids, - .filter = bpf_get_file_xattr_filter, + .set = &lsm_kfunc_set_ids, + .filter = bpf_lsm_kfunc_filter, }; -static int __init bpf_fs_kfuncs_init(void) +static int __init bpf_lsm_kfuncs_init(void) { - return register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_fs_kfunc_set); + return register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_lsm_kfunc_set); } -late_initcall(bpf_fs_kfuncs_init); +late_initcall(bpf_lsm_kfuncs_init); static const struct bpf_func_proto * bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) From patchwork Wed Mar 6 07:39:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583436 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C09CD5C908 for ; Wed, 6 Mar 2024 07:39:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710779; cv=none; b=bqmXJG17mJxGAJCKj4xBB9GCu8LGsVDURvuiZRmL4t+cgOQ0aOZ6zpG1DWB7T5kh6im589T9YOgKsF/ipmL9aQ6ZcSlnjlnSnetZaDdrEMvc7jA3j/yPWfDDA/2NsaXpOoNOdIGGgvhugns+fwEmSz14l/YYk09xAusr3ZtzcK8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710779; c=relaxed/simple; bh=SjcPFs4FSNGJVgC8/xMl+u/Ln8ryXAZgM6Iqr7AKav8=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=lzicwcepsxTmRcAYVfaydLWloIeIXOfXJxakCCpi5o0h8d2Jnj+ejF8WPxvOYKAb0inL031gMLZU24vg72C68Ht7q7jKARYR4rv2rLvCWJthQrIhJRIsxQivP8zG2iOrdncume1w97Rvehu8mmqUmfaetIpq231XrUZtlOcYdxQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=e9ONgnqH; arc=none smtp.client-ip=209.85.208.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="e9ONgnqH" Received: by mail-ed1-f49.google.com with SMTP id 4fb4d7f45d1cf-5673f7b3196so4138706a12.1 for ; Tue, 05 Mar 2024 23:39:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710776; x=1710315576; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=Qxd4dSDwNv99KGxLpWUkcR9yGfGt5zeMhN6bbg1OOSY=; b=e9ONgnqH1+Bcbdfc84yzWIlabT7FE0a9H11/wM8LJ1/C/+yQCgWn/7XKeAHqOTj2Ie DYBlWNWB+JNdtKjq/jimQc7k1Y8TsoPAY2aqFLlbTYjrpj+AjWodVpFpFEArHAAnRbIh iodMIaVUxA3DESanSDyn83De5e9yqxfmP/eRnnjA4PO+eh55I1A1m4KnHdqaKyb6+/Gg NiH/RNc8tcnlu6JJfm6EMoZU/qjtfOdHvsGP5Ti8JlA2UUwAQUmfWQMp8lwnnaHoFf6V ADnHxGgJxQink44oLg6wSst9/AtkIBNkRClhFv/hrmfTATUhKD426W0KQdaMD/m18k/f 1Tgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710776; x=1710315576; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Qxd4dSDwNv99KGxLpWUkcR9yGfGt5zeMhN6bbg1OOSY=; b=JGuzrUsmK66oeBMq3zehm2Y01kr55KMuMLGg/disEHviE9Pl04K+uG/AzzrY3eYvZ4 4K4byiU1/JPfc5fC8P3vlzUtuMYrOmJH3U7171m/a7qdk7I5JnQzcsDBkJKi29mOLqQF tQdrNsRweqvhMDQb3nbIpyp8g1WZzxJfkPAozlsUfvykubOmVjXBMXyFt0h8Elfcv6ck u3DYP28yc8K3wQSeZeVvj/18rbtl5h3iCyhob1C/e2K5cwKILhwzPNGmde3yXmQYQom7 KspQ1XC8zo+b0n/HC90gwERbs4mMlfFCU7wWG3XfdeRVb/c/Ewhnv19iRSJGmG45x6/y vwlw== X-Gm-Message-State: AOJu0Ywv1uzCxyeM5u7BuwTD4y7AOQfYnPw3ZM5XIa83jt1uUpCoxVkc mAFIoF9s5zUQZXUy4ujuwttCmsJzE99tqX9roUl+GXkPCaFhGq3hNYmNRJRQYd0gC0H5/Azm9en +IA== X-Google-Smtp-Source: AGHT+IFrTJ3SPPS2VPtMnyftJIZ3jaBujsED6xYduhc/AQg4M3oootOZLPE4aPQqjEP7HRt9tCujOQ== X-Received: by 2002:a17:906:7192:b0:a45:a928:8b65 with SMTP id h18-20020a170906719200b00a45a9288b65mr2845141ejk.28.1709710775587; Tue, 05 Mar 2024 23:39:35 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id l18-20020a1709060e1200b00a459094cf61sm1969118eji.115.2024.03.05.23.39.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:39:35 -0800 (PST) Date: Wed, 6 Mar 2024 07:39:31 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 2/9] bpf: add new acquire/release BPF kfuncs for mm_struct Message-ID: References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net A BPF LSM program will at times introspect the mm_struct that is nested within a given task_struct. Such introspection performed by a BPF LSM program may involve reading virtual addresses out from fields like arg_start/arg_end and env_start/env_end, or reading fields directly out from the backing exe_file. In order to perform reliable reads against fields contained within mm_struct, we need to introduce a new set of BPF kfuncs that have the ability to acquire and release references on the mm_struct that is nested within a task_struct. The following BPF kfuncs have been added in order to support this capability: struct mm_struct *bpf_task_mm_grab(struct task_struct *task); void bpf_mm_drop(struct mm_struct *mm); These new BPF kfuncs are pretty self-explanatory, but in kernel terms bpf_task_mm_grab() effectively allows you to get a reference on the mm_struct nested within a supplied task_struct. Whereas, bpf_mm_drop() allows you put a reference on a previously gotten mm_struct reference. Both BPF kfuncs are also backed by BPF's respective KF_ACQUIRE/KF_RELEASE semantics, ensuring that the BPF program behaves in accordance to the constraints enforced upon it when operating on reference counted in-kernel data structures. Notably, these newly added BPF kfuncs are simple wrappers around the mmgrab() and mmdrop() in-kernel helpers. Both mmgrab() and mmdrop() are used in favour of their somewhat similar counterparts mmget() and mmput() as they're considered to be the more lightweight variants in comparison, and there's no requirement to also pin the underlying address spaces just yet. Signed-off-by: Matt Bobrowski --- kernel/trace/bpf_trace.c | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index f639663ac339..801808b6efb0 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1473,10 +1473,57 @@ __bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str, return __vfs_getxattr(dentry, dentry->d_inode, name__str, value, value_len); } +/** + * bpf_task_mm_grab - get a reference on the mm_struct nested within the + * supplied task_struct + * @task: task_struct nesting the mm_struct that is to be referenced + * + * Grab a reference on the mm_struct that is nested within the supplied + * *task*. This kfunc will return NULL for threads that do not possess a valid + * mm_struct. For example, those that are flagged as PF_KTHREAD. A reference on + * a mm_struct acquired by this kfunc must be released using bpf_mm_drop(). + * + * This helper only pins the mm_struct and not necessarily the address space + * associated with the referenced mm_struct that is returned from this + * kfunc. Internally, this kfunc leans on mmgrab(), such that calling + * bpf_task_mm_grab() would be analogous to calling mmgrab() outside of BPF + * program context. + * + * Return: A referenced pointer to the mm_struct nested within the supplied + * *task*, or NULL. + */ +__bpf_kfunc struct mm_struct *bpf_task_mm_grab(struct task_struct *task) +{ + struct mm_struct *mm; + + task_lock(task); + mm = task->mm; + if (likely(mm)) + mmgrab(mm); + task_unlock(task); + + return mm; +} + +/** + * bpf_mm_drop - put a reference on the supplied mm_struct + * @mm: mm_struct of which to put a reference on + * + * Put a reference on the supplied *mm*. This kfunc internally leans on + * mmdrop(), such that calling bpf_mm_drop() would be analogous to calling + * mmdrop() outside of BPF program context. + */ +__bpf_kfunc void bpf_mm_drop(struct mm_struct *mm) +{ + mmdrop(mm); +} + __bpf_kfunc_end_defs(); BTF_KFUNCS_START(lsm_kfunc_set_ids) BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) +BTF_ID_FLAGS(func, bpf_task_mm_grab, KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL); +BTF_ID_FLAGS(func, bpf_mm_drop, KF_RELEASE); BTF_KFUNCS_END(lsm_kfunc_set_ids) static int bpf_lsm_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id) From patchwork Wed Mar 6 07:39:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583437 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6666D5D474 for ; Wed, 6 Mar 2024 07:39:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710791; cv=none; b=aDYcjkF3uYy3lmqNH55RQRDl8poW/OfntRqtJA19W3uO++WTkdsALUI6YruuYWRtTZy/wFb6WiAd1mYu00tsm2o773fmWNAPNtTqcWTVC7svMYJNJ4E9cKJdbN05/BEXc0ZRGW/eYKlxQT0ZH6JaqHQ7Tvnrww5VLpWwSzHG+9Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710791; c=relaxed/simple; bh=j0BU+hdZp/Ekkgm4kRDElt6pVQ3Oqng2XJrJl/gH0ec=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=Ihx9TXN7pUlmLz0MWAs4Jmirue61Nc+u/kJDjo9flh9vXUby2jLCtUoDPTM2CPd0NzpG3Wtq4Um5o951l9QqGXf/g5UhE6Ly+MNgBMftjAXp+Eza92wryjopsC0OSRoMLaAlKb4xPXg1bpSX7rRy+gNBzJTiF9e1lGVQ/K9Rr04= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=TnklPJAL; arc=none smtp.client-ip=209.85.218.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="TnklPJAL" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-a458eb7db13so75630566b.2 for ; Tue, 05 Mar 2024 23:39:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710787; x=1710315587; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=EfIYbSjn/LFCJX5yYTnie0A0VZaeiLz17KaDnMsDNwk=; b=TnklPJALs6vNjzjwHvQEZjhVjEYR4eV1HuBmzpk3Q76Nu3rtK6Jwqjhg0pZnIXkQB8 TfoEYF+wBgl46heLTC7mmIgZbfl38NoMJQcgYXekCkZr8bsJnfohDJt5mMu77AEN7ALB 3mUO0zLcfEf/N487A2b0sOIE+9jM06AUgFc5tCchqFQNbvp18wQ0RMpO3ftL1Xbv1PDX jBfM2kZcvk9wV2JxKi06psf0Uccf3ou9nL+JcFIA3iNiB0LLfXIEgLEvO7BjlADQ5YlZ 3B44MaaVUapfHLhq9onuak3kj9ZjtVanzO0S3fl99ZNPSnArO6vCKf5EDXdWPBjlBeJi yK0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710787; x=1710315587; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=EfIYbSjn/LFCJX5yYTnie0A0VZaeiLz17KaDnMsDNwk=; b=mbsRDIlow7ZdlsABzm3bkk7XLGuAM1DthLDc3lYD21bNEEKnTnTkKPd4pifl8Hmauh 9FhVZ5PKXKXdWdXjTTlzeU2K+MSNg22e1tPSBeaGm49rARQFjIs2Ykdra3L3rjhz1bKG iwga6i4q7P1LkAOt5RlxdAZ4UUIYbv+iOHg0iH3G8w9ncEEgq6DkJ40StlNfFvkEsrhV Nl7P0PpQmHtk9N1u4lG5z33KdfqUxYKsYM55ANqhPxotuCzyXrKh17d1NQ2KvErzkf4O ORXkGfwJDOTC/5oArOgFCqTUblQBxPEeRh+D+exclwNaF5xuLHW3/WbN0M/qdI50T/4u z0Tg== X-Gm-Message-State: AOJu0Yw2OURqu5cXfRn8eM/53WKxDTW78ygJma31ybLHvXrc8NeLxteE 0EwWF77WReDu0LXaaa1OqXyq+CQ3TsW9u77kZLhn+GkNN9fyIbKRSVY4GdIL7YaEGI6LLzC/UAA CmQ== X-Google-Smtp-Source: AGHT+IEGm8Yg+W/a57m3eOInaBG+TLKqaXf+oNU0QTYTrMYCDZOVdkycqurZRK7OmHpVAX/4OSlN2A== X-Received: by 2002:a17:906:f108:b0:a43:e63b:2ecc with SMTP id gv8-20020a170906f10800b00a43e63b2eccmr9777081ejb.67.1709710787504; Tue, 05 Mar 2024 23:39:47 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id k23-20020a1709063e1700b00a42f6d48c72sm6909943eji.145.2024.03.05.23.39.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:39:47 -0800 (PST) Date: Wed, 6 Mar 2024 07:39:43 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 3/9] bpf/selftests: add selftests for mm_struct acquire/release BPF kfuncs Message-ID: <84fc8c3698b4ee83eece7ecef902a1a9a416eafb.1709675979.git.mattbobrowski@google.com> References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net Add a new mm_kfunc test suite that is responsible for verifying the behaviour of the newly added mm_struct based BPF kfuncs. As of now, these selftests cover the operability of the following: struct mm_struct *bpf_task_mm_grab(struct task_struct *task); void bpf_mm_drop(struct mm_struct *mm); Signed-off-by: Matt Bobrowski --- .../selftests/bpf/prog_tests/mm_kfunc.c | 48 ++++++++ .../selftests/bpf/progs/mm_kfunc_common.h | 19 ++++ .../selftests/bpf/progs/mm_kfunc_failure.c | 103 ++++++++++++++++++ .../selftests/bpf/progs/mm_kfunc_success.c | 30 +++++ 4 files changed, 200 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/mm_kfunc.c create mode 100644 tools/testing/selftests/bpf/progs/mm_kfunc_common.h create mode 100644 tools/testing/selftests/bpf/progs/mm_kfunc_failure.c create mode 100644 tools/testing/selftests/bpf/progs/mm_kfunc_success.c diff --git a/tools/testing/selftests/bpf/prog_tests/mm_kfunc.c b/tools/testing/selftests/bpf/prog_tests/mm_kfunc.c new file mode 100644 index 000000000000..aece5c25486d --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/mm_kfunc.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#define _GNU_SOURCE +#include + +#include "mm_kfunc_failure.skel.h" +#include "mm_kfunc_success.skel.h" + +static void run_test(const char *prog_name) +{ + struct bpf_link *link; + struct bpf_program *prog; + struct mm_kfunc_success *skel; + + skel = mm_kfunc_success__open_and_load(); + if (!ASSERT_OK_PTR(skel, "mm_kfunc_success__open_and_load")) + return; + + link = NULL; + prog = bpf_object__find_program_by_name(skel->obj, prog_name); + if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) + goto cleanup; + + link = bpf_program__attach(prog); + ASSERT_OK_PTR(link, "bpf_program__attach"); +cleanup: + bpf_link__destroy(link); + mm_kfunc_success__destroy(skel); +} + +static const char * const success_tests[] = { + "task_mm_grab_drop_from_argument", + "task_mm_acquire_release_from_current", +}; + +void test_mm_kfunc(void) +{ + int i = 0; + + for (; i < ARRAY_SIZE(success_tests); i++) { + if (!test__start_subtest(success_tests[i])) + continue; + run_test(success_tests[i]); + } + + RUN_TESTS(mm_kfunc_failure); +} diff --git a/tools/testing/selftests/bpf/progs/mm_kfunc_common.h b/tools/testing/selftests/bpf/progs/mm_kfunc_common.h new file mode 100644 index 000000000000..043d74d4148b --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mm_kfunc_common.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#ifndef _MM_KFUNC_COMMON_H +#define _MM_KFUNC_COMMON_H + +#include +#include +#include +#include + +#include "bpf_misc.h" + +struct mm_struct *bpf_task_mm_grab(struct task_struct *task) __ksym; +void bpf_mm_drop(struct mm_struct *mm) __ksym; + +char _license[] SEC("license") = "GPL"; + +#endif /* _MM_KFUNC_COMMON_H */ diff --git a/tools/testing/selftests/bpf/progs/mm_kfunc_failure.c b/tools/testing/selftests/bpf/progs/mm_kfunc_failure.c new file mode 100644 index 000000000000..d818dfcab20e --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mm_kfunc_failure.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "mm_kfunc_common.h" + +SEC("lsm.s/file_open") +__failure __msg("Possibly NULL pointer passed to trusted arg0") +int BPF_PROG(task_mm_grab_null_kfunc) +{ + struct mm_struct *acquired; + + /* Can't pass a NULL pointer to bpf_task_mm_grab(). */ + acquired = bpf_task_mm_grab(NULL); + if (!acquired) + return 0; + bpf_mm_drop(acquired); + + return 0; +} + +SEC("lsm/task_free") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(task_mm_grab_from_lsm_task_free_kfunc, struct task_struct *task) +{ + struct mm_struct *acquired; + + /* The task_struct supplied to this LSM hook isn't trusted. */ + acquired = bpf_task_mm_grab(task); + if (!acquired) + return 0; + bpf_mm_drop(acquired); + + return 0; +} + +SEC("lsm.s/task_alloc") +__failure __msg("arg#0 pointer type STRUCT task_struct must point") +int BPF_PROG(task_mm_grab_fp_kfunc, struct task_struct *task, u64 clone_flags) +{ + struct task_struct *fp; + struct mm_struct *acquired; + + fp = (struct task_struct *)&clone_flags; + /* Can't pass random frame pointer to bpf_task_mm_grab(). */ + acquired = bpf_task_mm_grab(fp); + if (!acquired) + return 0; + bpf_mm_drop(acquired); + + return 0; +} + +SEC("lsm.s/task_alloc") +__failure __msg("Unreleased reference") +int BPF_PROG(task_mm_grab_unreleased_kfunc, struct task_struct *task) +{ + struct mm_struct *acquired; + + acquired = bpf_task_mm_grab(task); + __sink(acquired); + + /* Acquired but never released. */ + return 0; +} + +SEC("lsm.s/task_alloc") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(task_mm_drop_untrusted_kfunc, struct task_struct *task) +{ + struct mm_struct *acquired; + + /* task->mm from struct task_struct yields an untrusted pointer. */ + acquired = task->mm; + if (!acquired) + return 0; + bpf_mm_drop(acquired); + + return 0; +} + +SEC("lsm/vm_enough_memory") +__failure __msg("release kernel function bpf_mm_drop expects") +int BPF_PROG(mm_drop_unacquired_kfunc, struct mm_struct *mm) +{ + /* Can't release an unacquired pointer. */ + bpf_mm_drop(mm); + + return 0; +} + +SEC("lsm/vm_enough_memory") +__failure __msg("arg#0 pointer type STRUCT mm_struct must point") +int BPF_PROG(mm_drop_fp_kfunc, struct mm_struct *mm, long pages) +{ + struct mm_struct *fp; + + fp = (struct mm_struct *)&pages; + + /* Can't release random frame pointer. */ + bpf_mm_drop(fp); + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/mm_kfunc_success.c b/tools/testing/selftests/bpf/progs/mm_kfunc_success.c new file mode 100644 index 000000000000..5400abd2ee2d --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mm_kfunc_success.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "mm_kfunc_common.h" + +SEC("lsm.s/task_alloc") +int BPF_PROG(task_mm_grab_drop_from_argument, struct task_struct *task) +{ + struct mm_struct *acquired; + + acquired = bpf_task_mm_grab(task); + if (!acquired) + return 0; + bpf_mm_drop(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +int BPF_PROG(task_mm_acquire_release_from_current) +{ + struct mm_struct *acquired; + + acquired = bpf_task_mm_grab(bpf_get_current_task_btf()); + if (!acquired) + return 0; + bpf_mm_drop(acquired); + + return 0; +} From patchwork Wed Mar 6 07:40:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583438 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ed1-f48.google.com (mail-ed1-f48.google.com [209.85.208.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DF415CDC7 for ; Wed, 6 Mar 2024 07:40:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710808; cv=none; b=ct6n3xgfYQOJM83yC48ZxSa6pb18FJS7zea/2hvhZoAIZIl869yWeTNQ7PB7y5V3yurCsAiOBRbQUs47yJ6edsPe1l9kpUGRFnrHEO50ivTUKesYCIaXJGWTA2vGyWMsTbLZgLxJ41hQfNsYGELrCQUmcJFYNwlJaId0Jpdbldk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710808; c=relaxed/simple; bh=jq60zMaSYvap6aAng0em1/G5L7a9DGNMvLjFXCU8hFM=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=ljwiE17L7MPE1gn5izJb3rOsiX7uuw/vDeSk0CDCEZK0NT6+Bn7539B1UZDy8l0OwGE+nc1FeITjlj4/qW61U5JHPMQonhp+ALRNM1rV/Julg0EDHQN8mGQpFKycf6A6eJCPGx9wLtKhQ25vxL0645iFmngpTXL23TtRagi+Obw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=kNsxmjIx; arc=none smtp.client-ip=209.85.208.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="kNsxmjIx" Received: by mail-ed1-f48.google.com with SMTP id 4fb4d7f45d1cf-56781070f38so960802a12.0 for ; Tue, 05 Mar 2024 23:40:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710804; x=1710315604; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=Wl6HqlXoH1hydmZl0rJB+QoZZFFcJVSr7o6LR8kaTiY=; b=kNsxmjIxX2ZkCluWMUeh/p9pPheAYrBy1i9LubydwTvMQosDHOmNhVOnRer0wqDO3x BlFxIz1rCJgYH4xehHGrALP824oiuQVVnwFE4ySQQVCX6EaVP0a3XScdn2WGZUHpJJWj zx4DxBcNxVY7SQKh0PhHJPGKcgVpNbDioc1XWOTX45aS30T+dB1D1uhZZffXxdNSc3vn FnGyNQUNqfl2ft8K9oRkDjrxbWlphISNsM20kRHnAtgVTQTEgZ6ytjxOYb/Q5hMUk7OA Acvx0ZyhMvUH4E5fBkb4UCnglB9Tc774xUKPIFVkCgxkYnW/qag41LPr8mGrEqlGMZdk tPsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710804; x=1710315604; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Wl6HqlXoH1hydmZl0rJB+QoZZFFcJVSr7o6LR8kaTiY=; b=e93Iuv0zvl7oLlK575N0SX8vuUpCrt9Z4LPKjXfbacngUfbOkkulWbSEA3DiH3jRvI Wh4SCf8SmXOsNW+MHFF8wgw5V9VE/gKEgCFPNE7Gb4egt0qDgc/D8PVXo3Ju5X1VYUse +mYVP3CpKAF9UsD6Ws/vqa+94uoAoBIIX1kKu9PYf2yxUrpmA4y/ootICstOII6xzQSb RKuTWLvK33pBH+JDlrVauSSphk2mt56rNfrQT0FMiCs2EhEfUWMhJRxcpXDzNKodNLm4 k/A1yOR238y4q/Ey/GZzmmtBb7MBeydIxddKqPvfEYo9GfY687Ah1YfbM5s4PhtzvDwQ DUbg== X-Gm-Message-State: AOJu0YwuBNBtSLfwcnkvRR8rrUveF9g4DhymLMcS7vtKB4VVoefER17j TO+UVNMR5vYmrFi4BpABwJTotxHTkfQNQeZUHskxKTZ2dPmoMquWtFIaX6ey+IGAjL5cJJN3sN7 hIA== X-Google-Smtp-Source: AGHT+IE7EqIFnAfKo/zl9xpP/NOjjZB5tY1XzeNM14K5O13PxAr4oa3MO7A59bxR5uAUg0vqJWfa8g== X-Received: by 2002:a17:906:b85a:b0:a43:fd2c:663b with SMTP id ga26-20020a170906b85a00b00a43fd2c663bmr4938275ejb.33.1709710804538; Tue, 05 Mar 2024 23:40:04 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id gq13-20020a170906e24d00b00a45621ded4bsm2851865ejb.146.2024.03.05.23.40.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:40:04 -0800 (PST) Date: Wed, 6 Mar 2024 07:40:00 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 4/9] bpf: add new acquire/release based BPF kfuncs for exe_file Message-ID: <6a5d425e52eb4d8f7539e841494eac36688ab0da.1709675979.git.mattbobrowski@google.com> References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net It is rather common for BPF LSM program types to perform the struct walk current->mm->exe_file and subsequently operate on fields of the backing file. At times, some of these operations involve passing a exe_file's field on to BPF helpers and such i.e. bpf_d_path(¤t->mm->exe_file->f_path). However, doing so isn't necessarily always reliable as the backing file that exe_file is pointing to may be in the midst of being torn down and handing anything contained within this file to BPF helpers and such can lead to memory corruption issues [0]. To alleviate possibly operating on semi-torn down instances of current->mm->exe_file we introduce a set of BPF kfuncs that posses KF_ACQUIRE/KF_RELEASE based semantics. Such BPF kfuncs will allow BPF LSM program types to reliably get/put a reference on a current->mm->exe_file. The following new BPF kfuncs have been added: struct file *bpf_get_task_exe_file(struct task_struct *task); struct file *bpf_get_mm_exe_file(struct mm_struct *mm); void bpf_put_file(struct file *f); Internally, these new BPF kfuncs simply call the preexisting in-kernel functions get_task_exe_file(), get_mm_exe_file(), and fput() accordingly. From a technical standpoint, there's absolutely no need to re-implement such helpers just for BPF as they're currently scoped to BPF LSM program types. Note that we explicitly do not explicitly rely on the use of very low level in-kernel functions like get_file_rcu() and get_file_active() to acquire a reference on current->mm->exe_file and such. This is super subtle code and we probably want to avoid exposing any such subtleties to BPF in the form of BPF kfuncs. Additionally, the usage of a double pointer i.e. struct file **, isn't something that the BPF verifier currently recognizes nor has any intention to recognize for the foreseeable future. [0] https://lore.kernel.org/bpf/CAG48ez0ppjcT=QxU-jtCUfb5xQb3mLr=5FcwddF_VKfEBPs_Dg@mail.gmail.com/ Signed-off-by: Matt Bobrowski --- kernel/trace/bpf_trace.c | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 801808b6efb0..539c58db74d7 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1518,12 +1518,68 @@ __bpf_kfunc void bpf_mm_drop(struct mm_struct *mm) mmdrop(mm); } +/** + * bpf_get_task_exe_file - get a reference on the exe_file associated with the + * mm_struct that is nested within the supplied + * task_struct + * @task: task_struct of which the nested mm_struct's exe_file is to be + * referenced + * + * Get a reference on the exe_file that is associated with the mm_struct nested + * within the supplied *task*. A reference on a file pointer acquired by this + * kfunc must be released using bpf_put_file(). Internally, this kfunc leans on + * get_task_exe_file(), such that calling bpf_get_task_exe_file() would be + * analogous to calling get_task_exe_file() outside of BPF program context. + * + * Return: A referenced pointer to the exe_file associated with the mm_struct + * nested in the supplied *task*, or NULL. + */ +__bpf_kfunc struct file *bpf_get_task_exe_file(struct task_struct *task) +{ + return get_task_exe_file(task); +} + +/** + * bpf_get_mm_exe_file - get a reference on the exe_file for the supplied + * mm_struct. + * @mm: mm_struct of which the exe_file to get a reference on + * + * Get a reference on the exe_file associated with the supplied *mm*. A + * reference on a file pointer acquired by this kfunc must be released using + * bpf_put_file(). Internally, this kfunc leans on get_mm_exe_file(), such that + * calling bpf_get_mm_exe_file() would be analogous to calling get_mm_exe_file() + * outside of BPF program context. + * + * Return: A referenced file pointer to the exe_file for the supplied *mm*, or + * NULL. + */ +__bpf_kfunc struct file *bpf_get_mm_exe_file(struct mm_struct *mm) +{ + return get_mm_exe_file(mm); +} + +/** + * bpf_put_file - put a reference on the supplied file + * @f: file of which to put a reference on + * + * Put a reference on the supplied *f*. + */ +__bpf_kfunc void bpf_put_file(struct file *f) +{ + fput(f); +} + __bpf_kfunc_end_defs(); BTF_KFUNCS_START(lsm_kfunc_set_ids) BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE | KF_TRUSTED_ARGS) BTF_ID_FLAGS(func, bpf_task_mm_grab, KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL); BTF_ID_FLAGS(func, bpf_mm_drop, KF_RELEASE); +BTF_ID_FLAGS(func, bpf_get_task_exe_file, + KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_get_mm_exe_file, + KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE | KF_SLEEPABLE) BTF_KFUNCS_END(lsm_kfunc_set_ids) static int bpf_lsm_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id) From patchwork Wed Mar 6 07:40:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583439 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A84E21B948 for ; Wed, 6 Mar 2024 07:40:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710814; cv=none; b=ciFV9xTjtqRqDkJCdJjQCfYcqChm3tZWJ9NbvGge7VlYRKrJLmJbZrFG1sCuXbH94IiJVRo++rY9DIDLDGjF8uZmMBO0A5PXywHpR4Jjj/dAeYbP1hE+sHmc9qJ4p7K1OJuA6qsk0wB1lvVmL5PU24WNhntMeEC+yKyhii3GAC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710814; c=relaxed/simple; bh=nWQLHiPbnXEnGTDf/+TEtdNmum1UyFfr09ckYAnfdxk=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=OwfStoVagClpmMBrsyUA93hJYe+q2m/qna4L7xmgXkfyVfL2HwjxDKv0YsKUe3vH+5g87Es12EZ5KcYvn+uXGdsAuhnV+6dol75F8MdH8j/FHwWb1zdXsxt0KAT7jYEdlme6mbWIDWmeW4VlFDzvbULZMG9RwVs2Dek+1JhEDLk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=KnnULtZN; arc=none smtp.client-ip=209.85.208.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="KnnULtZN" Received: by mail-ed1-f47.google.com with SMTP id 4fb4d7f45d1cf-563c595f968so9603029a12.0 for ; Tue, 05 Mar 2024 23:40:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710811; x=1710315611; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=rljFKl8ue5u0Qxh8hXuWfy8iHr7ecePt00Q5/9obMrs=; b=KnnULtZNCKHVECbmCem2h3PkcWCYRXHodlQrL6f3BF8DfnSu7UWGhJAIfG0rsZpuwW P0NrM+xc3YztPi/6eYfl/7Keyrpv3JTQ7wLcDDGXm1iBVRHEeckPcQ7CDF9ce3/upVcO hHaNdsgDdvnf9XPbzebPh7/JbNgHwEBHrwET6RW3eYbWDEEQqiWmNKT87m0PnY6HYCpG IUaBRARR7hlEVqx3E22xMML87oTWzBt6XdWF5lRckVu6/TOhHl+fpDDA52+Zum5I4In4 CfCiZUo9SmWKgLx4wXx0Evt7YKHc1DTgaU4ApN8VSEJCnB3CD6FbqO6JG0kHmO0wN22F dvUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710811; x=1710315611; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=rljFKl8ue5u0Qxh8hXuWfy8iHr7ecePt00Q5/9obMrs=; b=Vjwp8BxxKChprj8BCgCj/4EGxBv6X7KewfSqRtYpEV048SLD7yhPfJCQr82gcTMDda dd+2Zw8ol8ja1mu7bqBhD+W1CJ7MT53P1oiPIPOniq+wOZ40Y9i1AH6X53fXriwK1y/1 ePtq96+kPdIAMkjlceDpg2gpSdPutf/to0+xEsM/NGMsJUblbFnhTBkFQCGuh5iluX+A LtOuD3YtobpPX0emcMa1RDLcke2kW019Beyevjpwz8NC07oauGVjDJEUL373FMUTBiW0 nw0tDs2M1CMpOpiMsMm3z8WKV1ido29upaj0ZSo8pm8rkptyYOFvg+txhZwYC0qksjX7 hjBA== X-Gm-Message-State: AOJu0YwiXeJrALMmx9yp8udhAHh57FdcRGmRpuRBc6BmMY0nkjyqP4/4 IxMuZl2yNfaXoLoRyYHwFaYxY10tHfzLTFYHPqIMdD0XXO14PRcXyxlp592F7NjLsnLXIomEypU A4Q== X-Google-Smtp-Source: AGHT+IHcz3ExqTFeTnEFmHSWRdYzDZyhuqU88ooD/ZKl4Jnz3VkgtVgt/N8SeENAomI8plBbvipaDw== X-Received: by 2002:a05:6402:35cc:b0:566:f851:f53b with SMTP id z12-20020a05640235cc00b00566f851f53bmr11632189edc.35.1709710810715; Tue, 05 Mar 2024 23:40:10 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id z6-20020a05640240c600b005670d2c253csm4462526edb.13.2024.03.05.23.40.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:40:10 -0800 (PST) Date: Wed, 6 Mar 2024 07:40:06 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 5/9] bpf/selftests: add selftests for exe_file acquire/release BPF kfuncs Message-ID: <9c9a652a26671ce5d1278148e63bb8903024031e.1709675979.git.mattbobrowski@google.com> References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net Add a new exe_file_kfunc test suite that is responsible for verifying the behaviour of the newly added exe_file based BPF kfuncs. For now, this new exe_file_kfunc test suite covers the following BPF kfuncs: struct file *bpf_get_task_exe_file(struct task_struct *task); struct file *bpf_get_mm_exe_file(struct mm_struct *mm); void bpf_put_file(struct file *f); Signed-off-by: Matt Bobrowski --- .../selftests/bpf/prog_tests/exe_file_kfunc.c | 49 +++++ .../bpf/progs/exe_file_kfunc_common.h | 23 +++ .../bpf/progs/exe_file_kfunc_failure.c | 181 ++++++++++++++++++ .../bpf/progs/exe_file_kfunc_success.c | 52 +++++ 4 files changed, 305 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/exe_file_kfunc.c create mode 100644 tools/testing/selftests/bpf/progs/exe_file_kfunc_common.h create mode 100644 tools/testing/selftests/bpf/progs/exe_file_kfunc_failure.c create mode 100644 tools/testing/selftests/bpf/progs/exe_file_kfunc_success.c diff --git a/tools/testing/selftests/bpf/prog_tests/exe_file_kfunc.c b/tools/testing/selftests/bpf/prog_tests/exe_file_kfunc.c new file mode 100644 index 000000000000..5900c1d4e820 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/exe_file_kfunc.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#define _GNU_SOURCE +#include + +#include "exe_file_kfunc_failure.skel.h" +#include "exe_file_kfunc_success.skel.h" + +static void run_test(const char *prog_name) +{ + struct bpf_link *link; + struct bpf_program *prog; + struct exe_file_kfunc_success *skel; + + skel = exe_file_kfunc_success__open_and_load(); + if (!ASSERT_OK_PTR(skel, "file_kfunc_success__open_and_load")) + return; + + link = NULL; + prog = bpf_object__find_program_by_name(skel->obj, prog_name); + if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) + goto cleanup; + + link = bpf_program__attach(prog); + ASSERT_OK_PTR(link, "bpf_program__attach"); +cleanup: + bpf_link__destroy(link); + exe_file_kfunc_success__destroy(skel); +} + +static const char * const success_tests[] = { + "get_task_exe_file_and_put_kfunc_from_current", + "get_task_exe_file_and_put_kfunc_from_argument", + "get_mm_exe_file_and_put_kfunc_from_current", +}; + +void test_exe_file_kfunc(void) +{ + int i = 0; + + for (; i < ARRAY_SIZE(success_tests); i++) { + if (!test__start_subtest(success_tests[i])) + continue; + run_test(success_tests[i]); + } + + RUN_TESTS(exe_file_kfunc_failure); +} diff --git a/tools/testing/selftests/bpf/progs/exe_file_kfunc_common.h b/tools/testing/selftests/bpf/progs/exe_file_kfunc_common.h new file mode 100644 index 000000000000..6623bcc130c3 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/exe_file_kfunc_common.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#ifndef _FILE_KFUNC_COMMON_H +#define _FILE_KFUNC_COMMON_H + +#include +#include +#include +#include + +#include "bpf_misc.h" + +struct mm_struct *bpf_task_mm_grab(struct task_struct *task) __ksym; +void bpf_mm_drop(struct mm_struct *mm) __ksym; + +struct file *bpf_get_task_exe_file(struct task_struct *task) __ksym; +struct file *bpf_get_mm_exe_file(struct mm_struct *mm) __ksym; +void bpf_put_file(struct file *f) __ksym; + +char _license[] SEC("license") = "GPL"; + +#endif /* _FILE_KFUNC_COMMON_H */ diff --git a/tools/testing/selftests/bpf/progs/exe_file_kfunc_failure.c b/tools/testing/selftests/bpf/progs/exe_file_kfunc_failure.c new file mode 100644 index 000000000000..8a4464481531 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/exe_file_kfunc_failure.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "exe_file_kfunc_common.h" + +SEC("lsm.s/file_open") +__failure __msg("Possibly NULL pointer passed to trusted arg0") +int BPF_PROG(get_task_exe_file_kfunc_null) +{ + struct file *acquired; + + /* Can't pass a NULL pointer to bpf_get_task_exe_file(). */ + acquired = bpf_get_task_exe_file(NULL); + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("Possibly NULL pointer passed to trusted arg0") +int BPF_PROG(get_mm_exe_file_kfunc_null) +{ + struct file *acquired; + + /* Can't pass a NULL pointer to bpf_get_mm_exe_file(). */ + acquired = bpf_get_mm_exe_file(NULL); + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/inode_getxattr") +__failure __msg("arg#0 pointer type STRUCT task_struct must point to scalar, or struct with scalar") +int BPF_PROG(get_task_exe_file_kfunc_fp) +{ + u64 x; + struct file *acquired; + struct task_struct *fp; + + fp = (struct task_struct *)&x; + /* Can't pass random frame pointer to bpf_get_task_exe_file(). */ + acquired = bpf_get_task_exe_file(fp); + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/inode_getxattr") +__failure __msg("arg#0 pointer type STRUCT mm_struct must point to scalar, or struct with scalar") +int BPF_PROG(get_mm_exe_file_kfunc_fp) +{ + int x; + struct file *acquired; + struct mm_struct *fp; + + fp = (struct mm_struct *)&x; + /* Can't pass random frame pointer to bpf_get_mm_exe_file(). */ + acquired = bpf_get_mm_exe_file(fp); + if (!acquired) + return 0; + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(get_task_exe_file_kfunc_untrusted) +{ + struct file *acquired; + struct task_struct *parent; + + /* Walking a trusted struct task_struct returned from + * bpf_get_current_task_btf() yields an untrusted pointer. */ + parent = bpf_get_current_task_btf()->parent; + /* Can't pass untrusted pointer to bpf_get_task_exe_file(). */ + acquired = bpf_get_task_exe_file(parent); + if (!acquired) + return 0; + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(get_mm_exe_file_kfunc_untrusted) +{ + struct file *acquired; + struct mm_struct *mm; + + /* Walking a struct task_struct obtained from bpf_get_current_task_btf() + * yields an untrusted pointer. */ + mm = bpf_get_current_task_btf()->mm; + /* Can't pass untrusted pointer to bpf_get_mm_exe_file(). */ + acquired = bpf_get_mm_exe_file(mm); + if (!acquired) + return 0; + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("Unreleased reference") +int BPF_PROG(get_task_exe_file_kfunc_unreleased) +{ + struct file *acquired; + + acquired = bpf_get_task_exe_file(bpf_get_current_task_btf()); + if (!acquired) + return 0; + __sink(acquired); + + /* Acquired but never released. */ + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("Unreleased reference") +int BPF_PROG(get_mm_exe_file_kfunc_unreleased) +{ + struct file *acquired; + struct mm_struct *mm; + + mm = bpf_task_mm_grab(bpf_get_current_task_btf()); + if (!mm) + return 0; + + acquired = bpf_get_mm_exe_file(mm); + if (!acquired) { + bpf_mm_drop(mm); + return 0; + } + __sink(acquired); + bpf_mm_drop(mm); + + /* Acquired but never released. */ + return 0; +} + +SEC("lsm/file_open") +__failure __msg("program must be sleepable to call sleepable kfunc bpf_put_file") +int BPF_PROG(put_file_kfunc_not_sleepable, struct file *f) +{ + struct file *acquired; + + acquired = bpf_get_task_exe_file(bpf_get_current_task_btf()); + if (!acquired) + return 0; + + /* Can't call bpf_put_file() from non-sleepable BPF program. */ + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("release kernel function bpf_put_file expects") +int BPF_PROG(put_file_kfunc_unacquired, struct file *f) +{ + /* Can't release an unacquired pointer. */ + bpf_put_file(f); + + return 0; +} + +SEC("tp_btf/task_newtask") +__failure __msg("calling kernel function bpf_get_task_exe_file is not allowed") +int BPF_PROG(get_task_exe_file_kfunc_not_lsm_prog, struct task_struct *task) +{ + struct file *acquired; + + /* bpf_get_task_exe_file() can only be called from BPF LSM program. */ + acquired = bpf_get_task_exe_file(bpf_get_current_task_btf()); + if (!acquired) + return 0; + bpf_put_file(acquired); + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/exe_file_kfunc_success.c b/tools/testing/selftests/bpf/progs/exe_file_kfunc_success.c new file mode 100644 index 000000000000..ae789cb0a9ae --- /dev/null +++ b/tools/testing/selftests/bpf/progs/exe_file_kfunc_success.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "exe_file_kfunc_common.h" + +SEC("lsm.s/file_open") +int BPF_PROG(get_task_exe_file_and_put_kfunc_from_current) +{ + struct file *acquired; + + acquired = bpf_get_task_exe_file(bpf_get_current_task_btf()); + if (!acquired) + return 0; + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/task_alloc") +int BPF_PROG(get_task_exe_file_and_put_kfunc_from_argument, + struct task_struct *task) +{ + struct file *acquired; + + acquired = bpf_get_task_exe_file(task); + if (!acquired) + return 0; + bpf_put_file(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +int BPF_PROG(get_mm_exe_file_and_put_kfunc_from_current) +{ + struct file *acquired; + struct mm_struct *mm; + + mm = bpf_task_mm_grab(bpf_get_current_task_btf()); + if (!mm) + return 0; + + acquired = bpf_get_mm_exe_file(mm); + if (!acquired) { + bpf_mm_drop(mm); + return 0; + } + bpf_put_file(acquired); + bpf_mm_drop(mm); + + return 0; +} From patchwork Wed Mar 6 07:40:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583440 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-oo1-f52.google.com (mail-oo1-f52.google.com [209.85.161.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 671605C91C for ; Wed, 6 Mar 2024 07:40:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710822; cv=none; b=QmzBOjEYz3CNSXimkaBYHGa0989UOhFAqzDrDgA2THTpUIAmZ/mJnO+uj4x5iLCMy+TJE3CLQHEqnwB2Nlnb+Qa1lhvW/MFVxiC1r5lZyVqy4RX04N/fwvwckcNpdb3N1TobIMsspupa3Ln9J9oVCfY6v2XMRYc6nTi+qjO+0Q8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710822; c=relaxed/simple; bh=U4vPSgjo1MPCWnJXUOvvXXEqOMay8Ii8QfHFiSKW29s=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=JBOME9SXroTOfYUF7j9IvBGVzLjd4PE0etqtmgX8HXFawIuI0Qncks99YJsDHg+UTpM3uGRWGGF5kG4Y5MjOnihTwzFncadndzB1CQuxjV8i6W2ioXw3ZAwA/PCJluPwTGCKYnCHQUxSJh23IFzYAEAXcR6tog/x800viWoOO3E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=TaMSQed7; arc=none smtp.client-ip=209.85.161.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="TaMSQed7" Received: by mail-oo1-f52.google.com with SMTP id 006d021491bc7-5a0b1936400so3005480eaf.2 for ; Tue, 05 Mar 2024 23:40:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710819; x=1710315619; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=Sm//KmoxbXbcsWPglbMLVIS1Px1eJWCW4kUeYbyxn5U=; b=TaMSQed7tiLHZyrBlIazF8lhqDqw49F7ifTFDbVNEv7+Seqsw/i0yFKBj0myqTnc9O I7vs9Q4PNyj4sLMqG1ZeZWS+dZhSGR8oDH6M3wMgdbI9zQ3ggkdgAFvIJrUg6qq6dZVR v1nqyLj4sEYgxx3xnim0snw07/0g3C9sZ5b5CPmmplNk/Ow/SqBVnMxe3l+kyf25a34v TQGPMumOXFtyOeicxzevF75amXdAItCLLPK57xqFjnSH4n0DhX12gPRGlvmY2/tXBLXA bumuhKqVEd7/B+g3um+mD5TmK+u22jqbIq9oaP7sAUzdoTXMt8PyRBrRqS5pJ1o9HmPF 3LBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710819; x=1710315619; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Sm//KmoxbXbcsWPglbMLVIS1Px1eJWCW4kUeYbyxn5U=; b=gy3Fe+ckmRAvKenINFVPovKuapQFhCaIM54kEfUSC6P2lozt/CkwjTo7ft8JaAjX4D BfE3TLa5l7t2QWwTvAVb7Uor88rzw0AAU4uYaOjumNfE7ISRrwOiKK/b64QXOdOyeRrp WbYZxG/oeOWcxLhOAjmU8YMfTLPmI016uU0+QffFJYvex4kufEKLMqczX2eC1VeDvN1D qe6d/5UrQ3PEgaBN6ba4tX9T8QzJs6HlZ0kX8HNszogcRENdW5Vf1Xe2corxrNmeyziE NZsxrwXYlUwUtzGeApY5M2J5EcnybDxrXfccRJxLdSxdbQuFJwEPfOc7AdRWPNOzZwps oDmw== X-Gm-Message-State: AOJu0Yy5acvxc/VDuSlVqipCC3h64mAxANhZoU203T36DOlg2uwAIr0I sx4J8++IHo9Z6wCJdZoOi9h0l8ABsnNN5qmb62GNp9sDSuaHFr1u3T+I50f6y9eXUdM+svKsNYk 06Q== X-Google-Smtp-Source: AGHT+IHmnIO9igbiizDOpzZIlfa7wqIYlpixrrFhSdvfq8QmXqsdRfEMPj7zalWSN0v34SoSWoRlvg== X-Received: by 2002:a4a:354d:0:b0:5a0:ea46:ffe9 with SMTP id w13-20020a4a354d000000b005a0ea46ffe9mr3948384oog.7.1709710818904; Tue, 05 Mar 2024 23:40:18 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id e18-20020a9d6e12000000b006e4cd29aecbsm749390otr.47.2024.03.05.23.40.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:40:18 -0800 (PST) Date: Wed, 6 Mar 2024 07:40:12 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 6/9] bpf: add acquire/release based BPF kfuncs for fs_struct's paths Message-ID: <458617e6f11863ecf8b3f83710a6606977c4c9cd.1709675979.git.mattbobrowski@google.com> References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net Add the ability to obtain a reference on the root and pwd paths which are nested within the fs_struct associated with a supplied task_struct. Both fs_struct's root and pwd are commonly operated on in BPF LSM program types and at times are further handed off to BPF helpers and such. There needs to be a mechanism that supports BPF LSM program types the ability to obtain stable handles to such paths in order to avoid possible memory corruption bugs [0]. We provide this mechanism through the introduction of the following new KF_ACQUIRE/KF_RELEASE BPF kfuncs: struct path *bpf_get_task_fs_root(struct task_struct *task); struct path *bpf_get_task_fs_pwd(struct task_struct *task); void bpf_put_path(struct path *path); Note that bpf_get_task_fs_root() and bpf_get_task_fs_pwd() are effectively open-coded variants of the in-kernel helpers get_fs_root() and get_fs_pwd(). We don't lean on these in-kernel helpers directly within the newly introduced BPF kfuncs as leaning on them would be rather awkward as we're wanting to return referenced path pointers directly BPF LSM program types. [0] https://lore.kernel.org/bpf/CAG48ez0ppjcT=QxU-jtCUfb5xQb3mLr=5FcwddF_VKfEBPs_Dg@mail.gmail.com/ Signed-off-by: Matt Bobrowski --- kernel/trace/bpf_trace.c | 83 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 539c58db74d7..84fd87ead20c 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -1569,6 +1570,83 @@ __bpf_kfunc void bpf_put_file(struct file *f) fput(f); } +/** + * bpf_get_task_fs_root - get a reference on the fs_struct's root path for the + * supplied task_struct + * @Task: task_struct of which the fs_struct's root path to get a reference on + * + * Get a reference on the root path nested within the fs_struct of the + * associated *task*. The referenced path retruned from this kfunc must be + * released using bpf_put_path(). + * + * Return: A referenced path pointer to the root path nested within the + * fs_struct of the supplied *task*, or NULL. + */ +__bpf_kfunc struct path *bpf_get_task_fs_root(struct task_struct *task) +{ + struct path *root; + struct fs_struct *fs; + + task_lock(task); + fs = task->fs; + if (unlikely(fs)) { + task_unlock(task); + return NULL; + } + + spin_lock(&fs->lock); + root = &fs->root; + path_get(root); + spin_unlock(&fs->lock); + task_unlock(task); + + return root; +} + +/** + * bpf_get_task_fs_pwd - get a reference on the fs_struct's pwd path for the + * supplied task_struct + * @task: task_struct of which the fs_struct's pwd path to get a reference on + * + * Get a reference on the pwd path nested within the fs_struct of the associated + * *task*. The referenced path retruned from this kfunc must be released using + * bpf_put_path(). + * + * Return: A referenced path pointer to the root path nested within the + * fs_struct of the supplied *task*, or NULL. + */ +__bpf_kfunc struct path *bpf_get_task_fs_pwd(struct task_struct *task) +{ + struct path *pwd; + struct fs_struct *fs; + + task_lock(task); + fs = task->fs; + if (unlikely(fs)) { + task_unlock(task); + return NULL; + } + + spin_lock(&fs->lock); + pwd = &fs->pwd; + path_get(pwd); + spin_unlock(&fs->lock); + task_unlock(task); + + return pwd; +} + +/** + * bpf_put_path - put a reference on the supplied path + * @path: path of which to put a reference on + * + * Put a reference on the supplied *path*. + */ +__bpf_kfunc void bpf_put_path(struct path *path) +{ + path_put(path); +} + __bpf_kfunc_end_defs(); BTF_KFUNCS_START(lsm_kfunc_set_ids) @@ -1580,6 +1658,11 @@ BTF_ID_FLAGS(func, bpf_get_task_exe_file, BTF_ID_FLAGS(func, bpf_get_mm_exe_file, KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE | KF_SLEEPABLE) +BTF_ID_FLAGS(func, bpf_get_task_fs_root, + KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_get_task_fs_pwd, + KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_put_path, KF_RELEASE | KF_SLEEPABLE) BTF_KFUNCS_END(lsm_kfunc_set_ids) static int bpf_lsm_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id) From patchwork Wed Mar 6 07:40:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583441 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-oi1-f182.google.com (mail-oi1-f182.google.com [209.85.167.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A14D5C90D for ; Wed, 6 Mar 2024 07:40:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710830; cv=none; b=G4T6rLEjCJCOXDtz8bLKhoLNnmHYDnA6WpGavW73XBio2kx0JnNfZorv/XVELjGQiAMR4u2NN5JyNNCi4JdnIx1RN7eidWgTj4eAJgvepG6D8C9/VPjF9ErpnFiqWkRkLpDu9XcvyPn1CSAWO00JL4w/V3qvc4VtEE34N2s06Oo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710830; c=relaxed/simple; bh=iLwHbf1oA5JxBnipUArq42l7X5KO0sj3Xs/LCM1ozFQ=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=iRJTQXUXMjClWo7qsIfNgaWDW5lq6S1uyvWbBZ5JPAF83URQ5AfrTau+J6cXpPRQF/UhmAYZ86AIO/zkVBaZbCTDhb8Sqv6Q72NA0MB8ocbe3rmdu5EHYJJ372ITcSd7m6Q92PgKz5bqrAD+oTdOZlTZQ6iIzT9hKKpbDwHLO9w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=B3U7IjL4; arc=none smtp.client-ip=209.85.167.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="B3U7IjL4" Received: by mail-oi1-f182.google.com with SMTP id 5614622812f47-3c1e992f060so1957032b6e.0 for ; Tue, 05 Mar 2024 23:40:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710827; x=1710315627; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=4298WmfQQE8gZH7rXnLK/a7brfP51MJX0hKZlrVvaHE=; b=B3U7IjL4ZRu4xEROnDLt1qZdriNC1IS6TKGWioMXq8AsDJ9WOS/rAd2Iudvu5amDmc uHW1tPqNCC6vMTHL/j5W81O2OUsLEggF4useMqR9nuoijbaD2sqvoHcXgro+3L9wmlI4 ppKmE6sH2+WRqWL0bPnZIai9zanGnYzmwy6IfLt4SIq/7XyIsp8zMYfBQmiiCd+nskQq 7PNg4py/ufAKFukAO7rnUkT75lG3MtzmEXonYVJD2/AY562+KBKCCAyWUYklY1lGEb4e 2HENmACGfq5pFmNKOd0MNc7eahVF9lYcAunGXrt9mjPCxe/5iXL1VAUtfM5GIab+Hs+E qVCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710827; x=1710315627; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=4298WmfQQE8gZH7rXnLK/a7brfP51MJX0hKZlrVvaHE=; b=c839f4zUhKJuNjiQeO91VQ1GMsr5duaWeFmQXlKiLs66kQyOX5VYsKDiieso26xoqO YYsG2FpGezVqma8hm+khz/rs/a8EU2SxUyOQzNdHT+WFwY1XucdusnwRJJEgNSUTauVd BeOxpxUjo3LbJFsLtli+xhfsQflGrrMaaAa8uhgWaMWodWxkuXgaoZquyGzx0B7B7Zxk SPSMBaKojRH9uu1N4n0GFuDkBIhb1I7KEyFKkRF3oymW6f8kEVK7pVLS+dFv/Rmeu+1n FF/xteIYP+1PSO7m+2tneaIbigNIk35fP7qsW+05Hm3eN0cBMl7dUgwOKaiLUUWdvhtt PCJA== X-Gm-Message-State: AOJu0YxosCTCCJD0Zv1CgFT2xRtPdYRNfbR0gx3lZDKZER/rEwqg8JEO EUEbzujvQD0xpuaSNz1etPNKIZdTUxuXvNhWl0ESawVbM2uioabJQ331vbWeehe4JK8ZhFmVQ6v rZw== X-Google-Smtp-Source: AGHT+IH1U4Q9kPYH7jD7X3wue28RHo6quR1tW4i0OCfLWlq2VwwtJ4Wz34z03CLCwuJbGB3bvEGeKg== X-Received: by 2002:a05:6808:1a91:b0:3c1:f46c:e71f with SMTP id bm17-20020a0568081a9100b003c1f46ce71fmr3586316oib.46.1709710827080; Tue, 05 Mar 2024 23:40:27 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id n30-20020a0568080a1e00b003c1973dbca6sm1317273oij.2.2024.03.05.23.40.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:40:26 -0800 (PST) Date: Wed, 6 Mar 2024 07:40:21 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 7/9] bpf/selftests: add selftests for root/pwd path based BPF kfuncs Message-ID: <1c7cdcb02209b99b92b1b006bad452c11d7ddd53.1709675979.git.mattbobrowski@google.com> References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net Add a new path_kfunc test suite that is responsible for verifiying the operability of the newly added root/pwd path based BPF kfuncs. This test suite covers the following BPF kfuncs: struct path *bpf_get_task_fs_root(struct task_struct *task); struct path *bpf_get_task_fs_pwd(struct task_struct *task); void bpf_put_path(struct path *path); Signed-off-by: Matt Bobrowski --- .../selftests/bpf/prog_tests/path_kfunc.c | 48 ++++++++ .../selftests/bpf/progs/path_kfunc_common.h | 20 +++ .../selftests/bpf/progs/path_kfunc_failure.c | 114 ++++++++++++++++++ .../selftests/bpf/progs/path_kfunc_success.c | 30 +++++ 4 files changed, 212 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/path_kfunc.c create mode 100644 tools/testing/selftests/bpf/progs/path_kfunc_common.h create mode 100644 tools/testing/selftests/bpf/progs/path_kfunc_failure.c create mode 100644 tools/testing/selftests/bpf/progs/path_kfunc_success.c diff --git a/tools/testing/selftests/bpf/prog_tests/path_kfunc.c b/tools/testing/selftests/bpf/prog_tests/path_kfunc.c new file mode 100644 index 000000000000..9a8701a7999c --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/path_kfunc.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#define _GNU_SOURCE +#include + +#include "path_kfunc_failure.skel.h" +#include "path_kfunc_success.skel.h" + +static void run_test(const char *prog_name) +{ + struct bpf_link *link; + struct bpf_program *prog; + struct path_kfunc_success *skel; + + skel = path_kfunc_success__open_and_load(); + if (!ASSERT_OK_PTR(skel, "path_kfunc_success__open_and_load")) + return; + + link = NULL; + prog = bpf_object__find_program_by_name(skel->obj, prog_name); + if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) + goto cleanup; + + link = bpf_program__attach(prog); + ASSERT_OK_PTR(link, "bpf_program__attach"); +cleanup: + bpf_link__destroy(link); + path_kfunc_success__destroy(skel); +} + +static const char * const success_tests[] = { + "get_task_fs_root_and_put_from_current", + "get_task_fs_pwd_and_put_from_current", +}; + +void test_path_kfunc(void) +{ + int i = 0; + + for (; i < ARRAY_SIZE(success_tests); i++) { + if (!test__start_subtest(success_tests[i])) + continue; + run_test(success_tests[i]); + } + + RUN_TESTS(path_kfunc_failure); +} diff --git a/tools/testing/selftests/bpf/progs/path_kfunc_common.h b/tools/testing/selftests/bpf/progs/path_kfunc_common.h new file mode 100644 index 000000000000..837dc03c136d --- /dev/null +++ b/tools/testing/selftests/bpf/progs/path_kfunc_common.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#ifndef _PATH_KFUNC_COMMON_H +#define _PATH_KFUNC_COMMON_H + +#include +#include +#include +#include + +#include "bpf_misc.h" + +char _license[] SEC("license") = "GPL"; + +struct path *bpf_get_task_fs_root(struct task_struct *task) __ksym; +struct path *bpf_get_task_fs_pwd(struct task_struct *task) __ksym; +void bpf_put_path(struct path *path) __ksym; + +#endif /* _PATH_KFUNC_COMMON_H */ diff --git a/tools/testing/selftests/bpf/progs/path_kfunc_failure.c b/tools/testing/selftests/bpf/progs/path_kfunc_failure.c new file mode 100644 index 000000000000..a28797e245e3 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/path_kfunc_failure.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "path_kfunc_common.h" + +SEC("lsm.s/file_open") +__failure __msg("Possibly NULL pointer passed to trusted arg0") +int BPF_PROG(get_task_fs_root_kfunc_null) +{ + struct path *acquired; + + /* Can't pass a NULL pointer to bpf_get_task_fs_root(). */ + acquired = bpf_get_task_fs_root(NULL); + if (!acquired) + return 0; + bpf_put_path(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("Possibly NULL pointer passed to trusted arg0") +int BPF_PROG(get_task_fs_pwd_kfunc_null) +{ + struct path *acquired; + + /* Can't pass a NULL pointer to bpf_get_task_fs_pwd(). */ + acquired = bpf_get_task_fs_pwd(NULL); + if (!acquired) + return 0; + bpf_put_path(acquired); + + return 0; +} + +SEC("lsm.s/task_alloc") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(get_task_fs_root_kfunc_untrusted, struct task_struct *task) +{ + struct path *acquired; + struct task_struct *parent; + + /* Walking the struct task_struct will yield an untrusted pointer. */ + parent = task->parent; + if (!parent) + return 0; + + acquired = bpf_get_task_fs_root(parent); + if (!acquired) + return 0; + bpf_put_path(acquired); + + return 0; +} + +SEC("lsm.s/task_alloc") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(get_task_fs_pwd_kfunc_untrusted, struct task_struct *task) +{ + struct path *acquired; + struct task_struct *parent; + + /* Walking the struct task_struct will yield an untrusted pointer. */ + parent = task->parent; + if (!parent) + return 0; + + acquired = bpf_get_task_fs_pwd(parent); + if (!acquired) + return 0; + bpf_put_path(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("Unreleased reference") +int BPF_PROG(get_task_fs_root_kfunc_unreleased) +{ + struct path *acquired; + + acquired = bpf_get_task_fs_root(bpf_get_current_task_btf()); + if (!acquired) + return 0; + __sink(acquired); + + /* Acquired but never released. */ + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("Unreleased reference") +int BPF_PROG(get_task_fs_pwd_kfunc_unreleased) +{ + struct path *acquired; + + acquired = bpf_get_task_fs_pwd(bpf_get_current_task_btf()); + if (!acquired) + return 0; + __sink(acquired); + + /* Acquired but never released. */ + return 0; +} + +SEC("lsm.s/inode_getattr") +__failure __msg("release kernel function bpf_put_path expects refcounted PTR_TO_BTF_ID") +int BPF_PROG(put_path_kfunc_unacquired, struct path *path) +{ + /* Can't release an unacquired pointer. */ + bpf_put_path(path); + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/path_kfunc_success.c b/tools/testing/selftests/bpf/progs/path_kfunc_success.c new file mode 100644 index 000000000000..8fc8e3c51405 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/path_kfunc_success.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "path_kfunc_common.h" + +SEC("lsm.s/file_open") +int BPF_PROG(get_task_fs_root_and_put_from_current) +{ + struct path *acquired; + + acquired = bpf_get_task_fs_root(bpf_get_current_task_btf()); + if (!acquired) + return 0; + bpf_put_path(acquired); + + return 0; +} + +SEC("lsm.s/file_open") +int BPF_PROG(get_task_fs_pwd_and_put_from_current) +{ + struct path *acquired; + + acquired = bpf_get_task_fs_pwd(bpf_get_current_task_btf()); + if (!acquired) + return 0; + bpf_put_path(acquired); + + return 0; +} From patchwork Wed Mar 6 07:40:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583443 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B0855CDED for ; Wed, 6 Mar 2024 07:40:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710837; cv=none; b=F2WVjCjnyfTC643QpzvgfJ/oBV48X+W6KstxuMVIi01VZ9uisVVvSs9AkGz+fpS+RQiZur3TxqwI9xzCSEqUHNUS8L9jIYyEgJpkJQFSU7WCm45OEuLrXfSiDe5ynYJhyn/H0DWJg3HUSDL6ve7VcvhgRvqd0TktIono5OvVUjA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710837; c=relaxed/simple; bh=ddtC+uKArv7UdiqQfjewNtYRkzLuCLfgVvW+TGa7IBM=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=pcMSe+u418kOT2Tdroyni9cV9503L2YqdfkTXav1vjXQAK3vtaxn2oMWYhljR/N0yyQPsVtz7VeWaWC9OaWneqgHbSo7LY/RopNn2loplwiaGHVUK/lVLIx+zX+NYJtp8+OKPv3XIU5dHOFWUhfxItLu7rJ1XcObGoh3JRNIfa4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=xyeBSyxq; arc=none smtp.client-ip=209.85.210.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="xyeBSyxq" Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-6ddca59e336so267485a34.0 for ; Tue, 05 Mar 2024 23:40:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710835; x=1710315635; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=dNwfyies9fK4BVkN1qpRBwPdhTsOnQT/qyn6MGfjNFo=; b=xyeBSyxqnFnYSu96xjr+jh7LR1kANzKZclTL/89+Mq9eiLWbe+6VR1ub4GupusB+eW Oa1IT7A1R5nckYfRqq6XFdNfdDAS8lPjXCGzbHgkqPz0ZvBbbgSM1Opwr3JF/aJ9Xf3z PIcLZnbiXQvVdqhSo3ScBWhwH0udkKt0gcnFpu/ihs5Iuyi6EWJOsmKNrqZ/Y5z1sYGr MUcOs6lJUsSz0rTwTK95G43LJHtvkW2nmiwCMVNpevCmL81fC684BNnHcpqe4vreRjgJ YpEnruTud1zsYtskWYceqXelRcUBmxhiJHtlX7Zcc5ULsQecp059JiPxDz2ywUpPSEDv IyVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710835; x=1710315635; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=dNwfyies9fK4BVkN1qpRBwPdhTsOnQT/qyn6MGfjNFo=; b=dzrN3mQQ/FI+rX9EZ5ZzTN9anhfSe5OweGUXuVfwLJJN3M2IGZo0pk5EH7a+JcTqa5 pyjXEInxiop8JZ0rTzCyQlSUqmvHGTPfM/L/if0pCi96Ozh35bYSZc65mFGPuC2CdQBI yChYugqsqwCvrS8RBw4TBjhAflf/yzRFskuyGx3UCKJO50PbfNzWoSkyq9ZnjUUwMMd2 amVQJvg5GE5Ayd+kvTPJLDgNYUz2Y1qb25U85ZwpAomebLCai7pYbjoMNghjFzqxEUZ2 ShlvDX6dcwSJS27Br//zqU71tMgaKj5i1534TidpqHBbnYVR96Oed8V2sUqp1rGj19Hz b7fw== X-Gm-Message-State: AOJu0YxnDgc6sXJMZuaNLPYufYHOqAjy5nomj+z89v0LbZggQlcTUJph mKkfFtSqzCEwphCcZLWxH0lNfuA1J7ay9E2vLTu4wqpPgwbiYgkonjYcSePhbRWIFSd6fZWn7ew OpA== X-Google-Smtp-Source: AGHT+IHSF6r7pWyah8Vo6aI+WZxk3Tmzs3eaCRP+IhPTHK+o4locRRAwnyg28TbdpJHarx1oGzZZ5Q== X-Received: by 2002:a9d:6d94:0:b0:6e4:ae29:d77f with SMTP id x20-20020a9d6d94000000b006e4ae29d77fmr1908819otp.6.1709710834670; Tue, 05 Mar 2024 23:40:34 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id z9-20020a9d7a49000000b006e4b6013ab2sm2183069otm.15.2024.03.05.23.40.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:40:34 -0800 (PST) Date: Wed, 6 Mar 2024 07:40:27 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 8/9] bpf: add trusted d_path() based BPF kfunc bpf_path_d_path() Message-ID: References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net The legacy bpf_d_path() helper did not operate on trusted pointer arguments, therefore under certain circumstances was susceptible to memory corruption issues [0]. This new d_path() based BPF kfunc bpf_path_d_path() makes use of the trusted pointer argument constraint KF_TRUSTED_ARGS. Making use of the KF_TRUSTED_ARGS constraint will ensure that d_path() may only be called when and underlying BPF program holds a stable handle for a given path. For now, we restrict bpf_path_d_path() to BPF LSM program types, but this may be relaxed in the future. Notably, we are consciously not retroactively enforcing the KF_TRUSTED_ARGS constraint onto the legacy bpf_d_path() helper, as that would lead to wide-scale BPF program breakage. [0] https://lore.kernel.org/bpf/CAG48ez0ppjcT=QxU-jtCUfb5xQb3mLr=5FcwddF_VKfEBPs_Dg@mail.gmail.com/ Signed-off-by: Matt Bobrowski --- kernel/trace/bpf_trace.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 84fd87ead20c..4989639153cd 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1647,6 +1647,37 @@ __bpf_kfunc void bpf_put_path(struct path *path) path_put(path); } +/** + * bpf_path_d_path - resolve the pathname for a given path + * @path: path to resolve the pathname for + * @buf: buffer to return the resolved path value in + * @buflen: length of the supplied buffer + * + * Resolve the pathname for the supplied trusted *path* in *buf*. This kfunc is + * the trusted/safer variant of the legacy bpf_d_path() helper and should be + * used in place of bpf_d_path() whenever possible. + * + * Return: A strictly positive integer corresponding to the length of the string + * representing the resolved pathname, including the NUL termination + * character. On error, a negative integer is returned. + */ +__bpf_kfunc int bpf_path_d_path(struct path *path, char *buf, int buflen) +{ + int len; + char *ret; + + if (buflen <= 0) + return -EINVAL; + + ret = d_path(path, buf, buflen); + if (IS_ERR(ret)) + return PTR_ERR(ret); + + len = buf + buflen - ret; + memmove(buf, ret, len); + return len; +} + __bpf_kfunc_end_defs(); BTF_KFUNCS_START(lsm_kfunc_set_ids) @@ -1663,6 +1694,7 @@ BTF_ID_FLAGS(func, bpf_get_task_fs_root, BTF_ID_FLAGS(func, bpf_get_task_fs_pwd, KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_put_path, KF_RELEASE | KF_SLEEPABLE) +BTF_ID_FLAGS(func, bpf_path_d_path, KF_TRUSTED_ARGS | KF_SLEEPABLE) BTF_KFUNCS_END(lsm_kfunc_set_ids) static int bpf_lsm_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id) From patchwork Wed Mar 6 07:40:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Bobrowski X-Patchwork-Id: 13583442 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-oo1-f54.google.com (mail-oo1-f54.google.com [209.85.161.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FF755CDED for ; Wed, 6 Mar 2024 07:40:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710835; cv=none; b=LeGqYKTNlWJAuHDCmwon+vBU1W9MJK5leWbcKxGidqGQ7g622IMEgA8iC/tV1xVVx3BXP9QpPgFtFCZAT0JJFDPuYFsbF9bSgVCfgHON8BdUl1vYJV69kmYdSwv9W+pG7o/8WVaCQLzhuSVVIaYfH/9H2GMHxIvPdtevg2Pn3cM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709710835; c=relaxed/simple; bh=Pj+o0wUiDrAZvuk8PrK4QBMqMvi5OoqumxrZvD4Kl9M=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=jdNKFjebWraP9V+JzWD3ea3ZHJp/P0BA02wDpDT2BYK9/l2OEJaL/Z4KeBhoEXS6QDqebh0HJ6+w6hGAefzI9m0Asmp2qHxLAaJ2Qa+E08Nw/hCXwf+3Zci0RYUTIY7E+vIPQAnh8aecKm4hWt43AnBoGegReKU9ToUaZ+NfomA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=e5Z7Hivw; arc=none smtp.client-ip=209.85.161.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="e5Z7Hivw" Received: by mail-oo1-f54.google.com with SMTP id 006d021491bc7-595aa5b1fe0so1008776eaf.2 for ; Tue, 05 Mar 2024 23:40:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709710832; x=1710315632; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=fH1k+SV/f0vvM8HD0mhAGfqzECUsbN8zTP2gm81qF5A=; b=e5Z7Hivw0M/ShryHD9fAt+sc97/QEoSKlPIAmS83+Z8nVaFogO8/38ipy41+1hNjrm SvfuHVP6vd8LhyoRU+H/wxRmcQFWyCwgwAgiS1U7bwHL5yXQE+wat15NUnZF4+dUPOW1 cEwO0G2dxjHPxo06y9lKTXLFnIrETIwflqNrGhzfqq9glp7pISZaAnEF+MWCqdDxUUnN eSuUaTGD880aF5Xc4QVX7rkrNle7FSm5em3OWV1h+0QSgCGTIhL3BMxppFb5LBkJ5Y0E BhKHV2cAknYdotlGsaFR38QXCRNcuUdGtbNyxlaz8XFSXuZF8IL3kWyvPlsCHbB2heM4 G8MA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709710832; x=1710315632; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=fH1k+SV/f0vvM8HD0mhAGfqzECUsbN8zTP2gm81qF5A=; b=krWHK4servHx2Q0OQcEyKWZAvBsn8LP75ezue6cpyBnBv8L2cT5VsPkgAb4Vzxm/sk Jijp7+x7CiHXNQYfmmP3OCbAtuxD+OalES3pN3kyWV9qlBYcqfNCIGtYvvtoPsysGVZH j/IYPGbnqstMwmsuAAC+51Qae3AXX53eTmLD2FSlnNqqVt4dz0fLXDJI1ZVEl2z6L257 XznIhO5l/cpkVk6jf5jXmayP26/kKgQiCX+iEzUZlNNmo6kFp1Vv2rlgPVwlSZ+QiBwJ 7FOF0Ajgy8/P2RME0cfu6IV2e6gmEerF7LaxQRYoMZmhKpjORSeu4TIFjQWnKMlZHKvU vptg== X-Gm-Message-State: AOJu0YxMPiRSP+m2P0WAv4w3xzd6S/C9R9DUB/z2pLgffZfY7StAELxs qtfeflhN+/NtUrDpucS8RS4usE45PqCz1UKLtdvw5TADL9zdtjOU72z8fKyaQ7C+X+RY0CpARi6 v0g== X-Google-Smtp-Source: AGHT+IFslANPT783zPiQEmQCglAKToxQEC4ZXx0rG+iPYroD1+COb5i4MmK62W2unVaTgUg6mCsULw== X-Received: by 2002:a05:6870:471f:b0:21f:a11a:e251 with SMTP id b31-20020a056870471f00b0021fa11ae251mr4336889oaq.5.1709710831768; Tue, 05 Mar 2024 23:40:31 -0800 (PST) Received: from google.com (12.196.204.35.bc.googleusercontent.com. [35.204.196.12]) by smtp.gmail.com with ESMTPSA id gb8-20020a056870670800b00220db41819bsm2152952oab.2.2024.03.05.23.40.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 23:40:31 -0800 (PST) Date: Wed, 6 Mar 2024 07:40:25 +0000 From: Matt Bobrowski To: bpf@vger.kernel.org Cc: ast@kernel.org, andrii@kernel.org, kpsingh@google.com, jannh@google.com, jolsa@kernel.org, daniel@iogearbox.net, brauner@kernel.org, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 bpf-next 9/9] bpf/selftests: adapt selftests test_d_path for BPF kfunc bpf_path_d_path() Message-ID: <9cf1f10d6f6f16095b8cea1d4291a54469542090.1709675979.git.mattbobrowski@google.com> References: Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Patchwork-Delegate: bpf@iogearbox.net Adapt the existing test_d_path test suite to cover the operability of the newly introduced trusted d_path() based BPF kfunc bpf_path_d_path(). This new BPF kfunc is functionally identical with regards to its path reconstruction based capabilities to that of its predecessor bpf_d_path(), so it makes sense to recycle the existing test_d_path suite. Signed-off-by: Matt Bobrowski --- .../testing/selftests/bpf/prog_tests/d_path.c | 80 +++++++++++++++++++ .../selftests/bpf/progs/d_path_common.h | 35 ++++++++ .../bpf/progs/d_path_kfunc_failure.c | 66 +++++++++++++++ .../bpf/progs/d_path_kfunc_success.c | 25 ++++++ .../testing/selftests/bpf/progs/test_d_path.c | 20 +---- .../bpf/progs/test_d_path_check_rdonly_mem.c | 8 +- .../bpf/progs/test_d_path_check_types.c | 8 +- 7 files changed, 209 insertions(+), 33 deletions(-) create mode 100644 tools/testing/selftests/bpf/progs/d_path_common.h create mode 100644 tools/testing/selftests/bpf/progs/d_path_kfunc_failure.c create mode 100644 tools/testing/selftests/bpf/progs/d_path_kfunc_success.c diff --git a/tools/testing/selftests/bpf/prog_tests/d_path.c b/tools/testing/selftests/bpf/prog_tests/d_path.c index ccc768592e66..cc5c886fe59b 100644 --- a/tools/testing/selftests/bpf/prog_tests/d_path.c +++ b/tools/testing/selftests/bpf/prog_tests/d_path.c @@ -11,6 +11,8 @@ #include "test_d_path.skel.h" #include "test_d_path_check_rdonly_mem.skel.h" #include "test_d_path_check_types.skel.h" +#include "d_path_kfunc_failure.skel.h" +#include "d_path_kfunc_success.skel.h" /* sys_close_range is not around for long time, so let's * make sure we can call it on systems with older glibc @@ -124,6 +126,13 @@ static void test_d_path_basic(void) struct test_d_path *skel; int err; + /* + * Carrying global state across test function invocations is super + * gross, but it was late and I was tired and I just wanted to get the + * darn test working. Zero'ing this out was a simple no brainer. + */ + memset(&src, 0, sizeof(src)); + skel = test_d_path__open_and_load(); if (CHECK(!skel, "setup", "d_path skeleton failed\n")) goto cleanup; @@ -195,8 +204,72 @@ static void test_d_path_check_types(void) test_d_path_check_types__destroy(skel); } +static struct bpf_path_d_path_t { + const char *prog_name; +} success_test_cases[] = { + { + .prog_name = "path_d_path_from_path_argument", + }, +}; + +static void test_bpf_path_d_path(struct bpf_path_d_path_t *t) +{ + int i, ret; + struct bpf_link *link; + struct bpf_program *prog; + struct d_path_kfunc_success__bss *bss; + struct d_path_kfunc_success *skel; + + /* + * Carrying global state across function invocations is super gross, but + * it was late and I was tired and I just wanted to get the darn test + * working. Zero'ing this out was a simple no brainer. + */ + memset(&src, 0, sizeof(src)); + + skel = d_path_kfunc_success__open(); + if (!ASSERT_OK_PTR(skel, "d_path_kfunc_success__open")) + return; + + bss = skel->bss; + bss->my_pid = getpid(); + + ret = d_path_kfunc_success__load(skel); + if (CHECK(ret, "setup", "d_path_kfunc_success__load\n")) + goto cleanup; + + link = NULL; + prog = bpf_object__find_program_by_name(skel->obj, t->prog_name); + if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) + goto cleanup; + + link = bpf_program__attach(prog); + if (!ASSERT_OK_PTR(link, "bpf_program__attach")) + goto cleanup; + + ret = trigger_fstat_events(bss->my_pid); + if (ret < 0) + goto cleanup; + + for (i = 0; i < MAX_FILES; i++) { + CHECK(strncmp(src.paths[i], bss->paths_stat[i], MAX_PATH_LEN), + "check", "failed to get stat path[%d]: %s vs %s\n", i, + src.paths[i], bss->paths_stat[i]); + CHECK(bss->rets_stat[i] != strlen(bss->paths_stat[i]) + 1, + "check", + "failed to match stat return [%d]: %d vs %zd [%s]\n", i, + bss->rets_stat[i], strlen(bss->paths_stat[i]) + 1, + bss->paths_stat[i]); + } +cleanup: + bpf_link__destroy(link); + d_path_kfunc_success__destroy(skel); +} + void test_d_path(void) { + int i = 0; + if (test__start_subtest("basic")) test_d_path_basic(); @@ -205,4 +278,11 @@ void test_d_path(void) if (test__start_subtest("check_alloc_mem")) test_d_path_check_types(); + + for (; i < ARRAY_SIZE(success_test_cases); i++) { + if (!test__start_subtest(success_test_cases[i].prog_name)) + continue; + test_bpf_path_d_path(&success_test_cases[i]); + } + RUN_TESTS(d_path_kfunc_failure); } diff --git a/tools/testing/selftests/bpf/progs/d_path_common.h b/tools/testing/selftests/bpf/progs/d_path_common.h new file mode 100644 index 000000000000..276331b5ff9f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/d_path_common.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#ifndef _D_PATH_COMMON_H +#define _D_PATH_COMMON_H + +#include +#include +#include + +#include "bpf_misc.h" + +#define MAX_PATH_LEN 128 +#define MAX_FILES 7 + +extern const int bpf_prog_active __ksym; +int bpf_path_d_path(struct path *path, char *buf, int buflen) __ksym; + +pid_t my_pid = 0; + +__u32 cnt_stat = 0; +__u32 cnt_close = 0; + +char paths_stat[MAX_FILES][MAX_PATH_LEN] = {}; +char paths_close[MAX_FILES][MAX_PATH_LEN] = {}; + +int rets_stat[MAX_FILES] = {}; +int rets_close[MAX_FILES] = {}; + +int called_stat = 0; +int called_close = 0; + +char _license[] SEC("license") = "GPL"; + +#endif /* _D_PATH_COMMON_H */ diff --git a/tools/testing/selftests/bpf/progs/d_path_kfunc_failure.c b/tools/testing/selftests/bpf/progs/d_path_kfunc_failure.c new file mode 100644 index 000000000000..9da5f0d395c9 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/d_path_kfunc_failure.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "d_path_common.h" + +char buf[MAX_PATH_LEN] = {}; + +SEC("lsm.s/file_open") +__failure __msg("Possibly NULL pointer passed to trusted arg0") +int BPF_PROG(path_d_path_kfunc_null) +{ + /* Can't pass NULL value to bpf_path_d_path() kfunc. */ + bpf_path_d_path(NULL, buf, sizeof(buf)); + return 0; +} + +SEC("fentry/vfs_open") +__failure __msg("calling kernel function bpf_path_d_path is not allowed") +int BPF_PROG(path_d_path_kfunc_non_lsm, struct path *path, struct file *f) +{ + /* Calling bpf_path_d_path() kfunc from a non-sleepable and non-LSM + * based program isn't permitted. + */ + bpf_path_d_path(path, buf, sizeof(buf)); + return 0; +} + +SEC("lsm.s/task_alloc") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(path_d_path_kfunc_untrusted_from_argument, struct task_struct *task) +{ + struct path *root; + + /* Walking a trusted argument yields an untrusted pointer. */ + root = &task->fs->root; + bpf_path_d_path(root, buf, sizeof(buf)); + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("R1 must be referenced or trusted") +int BPF_PROG(path_d_path_kfunc_untrusted_from_current) +{ + struct path *pwd; + struct task_struct *current; + + current = bpf_get_current_task_btf(); + /* Walking a trusted pointer returned from bpf_get_current_task_btf() + * yields and untrusted pointer. */ + pwd = ¤t->fs->pwd; + bpf_path_d_path(pwd, buf, sizeof(buf)); + return 0; +} + +SEC("lsm.s/file_open") +__failure __msg("R1 must have zero offset when passed to release func or trusted arg to kfunc") +int BPF_PROG(path_d_path_kfunc_trusted_variable_offset, struct file *file) +{ + /* Passing variable offsets from a trusted aren't supported just yet, + * despite being perfectly OK i.e. file->f_path. Once the BPF verifier + * has been updated to handle this case, this test can be removed. For + * now, ensure we reject the BPF program upon load if this is attempted. + */ + bpf_path_d_path(&file->f_path, buf, sizeof(buf)); + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/d_path_kfunc_success.c b/tools/testing/selftests/bpf/progs/d_path_kfunc_success.c new file mode 100644 index 000000000000..72d1a64618d1 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/d_path_kfunc_success.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Google LLC. */ + +#include "d_path_common.h" + +SEC("lsm.s/inode_getattr") +int BPF_PROG(path_d_path_from_path_argument, struct path *path) +{ + u32 cnt = cnt_stat; + int ret; + pid_t pid; + + pid = bpf_get_current_pid_tgid() >> 32; + if (pid != my_pid) + return 0; + + if (cnt >= MAX_FILES) + return 0; + + ret = bpf_path_d_path(path, paths_stat[cnt], MAX_PATH_LEN); + rets_stat[cnt] = ret; + cnt_stat++; + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/test_d_path.c b/tools/testing/selftests/bpf/progs/test_d_path.c index 84e1f883f97b..5bdfa4abb5f6 100644 --- a/tools/testing/selftests/bpf/progs/test_d_path.c +++ b/tools/testing/selftests/bpf/progs/test_d_path.c @@ -1,22 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 -#include "vmlinux.h" -#include -#include - -#define MAX_PATH_LEN 128 -#define MAX_FILES 7 - -pid_t my_pid = 0; -__u32 cnt_stat = 0; -__u32 cnt_close = 0; -char paths_stat[MAX_FILES][MAX_PATH_LEN] = {}; -char paths_close[MAX_FILES][MAX_PATH_LEN] = {}; -int rets_stat[MAX_FILES] = {}; -int rets_close[MAX_FILES] = {}; - -int called_stat = 0; -int called_close = 0; +#include "d_path_common.h" SEC("fentry/security_inode_getattr") int BPF_PROG(prog_stat, struct path *path, struct kstat *stat, @@ -61,5 +45,3 @@ int BPF_PROG(prog_close, struct file *file, void *id) cnt_close++; return 0; } - -char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/test_d_path_check_rdonly_mem.c b/tools/testing/selftests/bpf/progs/test_d_path_check_rdonly_mem.c index 27c27cff6a3a..6094a58321a4 100644 --- a/tools/testing/selftests/bpf/progs/test_d_path_check_rdonly_mem.c +++ b/tools/testing/selftests/bpf/progs/test_d_path_check_rdonly_mem.c @@ -1,11 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2022 Google */ -#include "vmlinux.h" -#include -#include - -extern const int bpf_prog_active __ksym; +#include "d_path_common.h" SEC("fentry/security_inode_getattr") int BPF_PROG(d_path_check_rdonly_mem, struct path *path, struct kstat *stat, @@ -24,5 +20,3 @@ int BPF_PROG(d_path_check_rdonly_mem, struct path *path, struct kstat *stat, } return 0; } - -char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/test_d_path_check_types.c b/tools/testing/selftests/bpf/progs/test_d_path_check_types.c index 7e02b7361307..6d4204136489 100644 --- a/tools/testing/selftests/bpf/progs/test_d_path_check_types.c +++ b/tools/testing/selftests/bpf/progs/test_d_path_check_types.c @@ -1,10 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 -#include "vmlinux.h" -#include -#include - -extern const int bpf_prog_active __ksym; +#include "d_path_common.h" struct { __uint(type, BPF_MAP_TYPE_RINGBUF); @@ -28,5 +24,3 @@ int BPF_PROG(d_path_check_rdonly_mem, struct path *path, struct kstat *stat, } return 0; } - -char _license[] SEC("license") = "GPL";