From: Wen Yang <wen.yang@linux.dev>
To: Joel Granados <j.granados@samsung.com>,
Luis Chamberlain <mcgrof@kernel.org>,
Kees Cook <keescook@chromium.org>
Cc: "Eric W . Biederman" <ebiederm@xmission.com>,
"Christian Brauner" <brauner@kernel.org>,
"Thomas Weißschuh" <thomas@t-8ch.de>,
linux-kernel@vger.kernel.org, "Wen Yang" <wen.yang@linux.dev>,
"Dave Young" <dyoung@redhat.com>
Subject: [RESEND PATCH v4 2/5] sysctl: support encoding values directly in the table entry
Date: Tue, 8 Oct 2024 23:14:05 +0800 [thread overview]
Message-ID: <20241008151444.12453-2-wen.yang@linux.dev> (raw)
In-Reply-To: <cover.1726907948.git.wen.yang@linux.dev>
Eric points out: "by turning .extra1 and .extra2 into longs instead of
keeping them as pointers and needing constants to be pointed at somewhere
.. The only people I can see who find a significant benefit by
consolidating all of the constants into one place are people who know how
to stomp kernel memory."
This patch supports encoding values directly in table entries through the
following work:
- extra1/extra2 and min/max are placed in one union to ensure compatibility
with previous code without increasing memory overhead, and then we could
gradually remove these unnecessary extra1/extra2.
- two bits were used to represent the information of the above union:
SYSCTL_FLAG_MIN: 0, using extra1. 1, using min.
SYSCTL_FLAG_MAX: 0, using extra2. 1, using max.
- since the proc file's mode field only uses 9 bits(777), we could use the
additional two bits(S_ISUID and S_ISGID) to temporarily represent
SYSCTL_FLAG_MIN and SYSCTL_FLAG_MAX.
- added some helper macros.
By introducing long min/max to replace void * extra1/extra2 in most cases,
unnecessary variables can be removed to save memory and avoid attacks.
Signed-off-by: Wen Yang <wen.yang@linux.dev>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Joel Granados <j.granados@samsung.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Dave Young <dyoung@redhat.com>
Cc: linux-kernel@vger.kernel.org
---
fs/proc/proc_sysctl.c | 8 ++++++--
include/linux/sysctl.h | 24 ++++++++++++++++++++----
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 90c99eb1abf6..e88d1dca2a80 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -848,8 +848,11 @@ static int proc_sys_getattr(struct mnt_idmap *idmap,
return PTR_ERR(head);
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
- if (table)
+ if (table) {
stat->mode = (stat->mode & S_IFMT) | table->mode;
+ stat->mode &= ~SYSCTL_FLAG_MIN;
+ stat->mode &= ~SYSCTL_FLAG_MAX;
+ }
sysctl_head_finish(head);
return 0;
@@ -1163,7 +1166,8 @@ static int sysctl_check_table(const char *path, struct ctl_table_header *header)
if (!entry->proc_handler)
err |= sysctl_err(path, entry, "No proc_handler");
- if ((entry->mode & (S_IRUGO|S_IWUGO)) != entry->mode)
+ if ((entry->mode & (S_IRUGO|S_IWUGO|SYSCTL_FLAG_MIN|SYSCTL_FLAG_MAX))
+ != entry->mode)
err |= sysctl_err(path, entry, "bogus .mode 0%o",
entry->mode);
}
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index edfcb22b1e3d..859b016aa76e 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -28,6 +28,7 @@
#include <linux/rbtree.h>
#include <linux/uidgid.h>
#include <uapi/linux/sysctl.h>
+#include <uapi/linux/stat.h>
/* For the /proc/sys support */
struct completion;
@@ -131,6 +132,9 @@ static inline void *proc_sys_poll_event(struct ctl_table_poll *poll)
#define DEFINE_CTL_TABLE_POLL(name) \
struct ctl_table_poll name = __CTL_TABLE_POLL_INITIALIZER(name)
+#define SYSCTL_FLAG_MIN S_ISUID
+#define SYSCTL_FLAG_MAX S_ISGID
+
/* A sysctl table is an array of struct ctl_table: */
struct ctl_table {
const char *procname; /* Text ID for /proc/sys, or zero */
@@ -139,8 +143,16 @@ struct ctl_table {
umode_t mode;
proc_handler *proc_handler; /* Callback for text formatting */
struct ctl_table_poll *poll;
- void *extra1;
- void *extra2;
+ union {
+ struct {
+ void *extra1;
+ void *extra2;
+ };
+ struct {
+ long min;
+ long max;
+ };
+ };
} __randomize_layout;
struct ctl_node {
@@ -212,9 +224,13 @@ struct ctl_table_root {
#define register_sysctl(path, table) \
register_sysctl_sz(path, table, ARRAY_SIZE(table))
-#define __SYSCTL_RANGE_MIN(_a, _b, _c) (((_a)->extra1) ? *(_b((_a)->extra1)) : (_c))
+#define __SYSCTL_RANGE_EXTRA1(_a, _b, _c) (((_a)->extra1) ? *(_b((_a)->extra1)) : (_c))
+#define __SYSCTL_RANGE_MIN(_a, _b, _c) ((((_a)->mode) & SYSCTL_FLAG_MIN) ? \
+ ((_a)->min) : __SYSCTL_RANGE_EXTRA1(_a, _b, _c))
-#define __SYSCTL_RANGE_MAX(_a, _b, _c) (((_a)->extra2) ? *(_b((_a)->extra2)) : (_c))
+#define __SYSCTL_RANGE_EXTRA2(_a, _b, _c) (((_a)->extra2) ? *(_b((_a)->extra2)) : (_c))
+#define __SYSCTL_RANGE_MAX(_a, _b, _c) ((((_a)->mode) & SYSCTL_FLAG_MAX) ? \
+ ((_a)->max) : __SYSCTL_RANGE_EXTRA2(_a, _b, _c))
static inline unsigned int sysctl_range_min_u8(const struct ctl_table *table)
{
--
2.25.1
next prev parent reply other threads:[~2024-10-08 15:15 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-08 15:14 [RESEND PATCH v4 0/5] sysctl: encode the min/max values directly in the table entry Wen Yang
2024-10-08 15:14 ` [RESEND PATCH v4 1/5] sysctl: add helper functions to extract table->extra1/extra2 Wen Yang
2024-10-08 15:14 ` Wen Yang [this message]
2024-10-08 15:14 ` [RESEND PATCH v4 3/5] sysctl: add kunit test code to check the min/max encoding of sysctl table entries Wen Yang
2024-10-08 15:14 ` [RESEND PATCH v4 4/5] sysctl: delete mmap_rnd_bits_{min/max} and mmap_rnd_compat_bits_{min/max} to save 16 bytes Wen Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241008151444.12453-2-wen.yang@linux.dev \
--to=wen.yang@linux.dev \
--cc=brauner@kernel.org \
--cc=dyoung@redhat.com \
--cc=ebiederm@xmission.com \
--cc=j.granados@samsung.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mcgrof@kernel.org \
--cc=thomas@t-8ch.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox