From 7ccf62a6edd8c50ee344a59be25c28d4faf29619 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Sat, 15 Feb 2025 18:17:46 +0700 Subject: [PATCH] LU-18186 libcfs: avoid kmalloc order > MAX_PAGE_ORDER WARNING: CPU: 4 PID: 448333 at mm/page_alloc.c:4663 __alloc_pages_noprof+0x3a7/0x4e0 libcfs calls memdup_user_nul() which uses kmalloc() which can trigger the above warning. Limit these excessive allocations a reasonable minimum. Signed-off-by: Shaun Tancheff Change-Id: Ide49aa3870cadc43c520f29b0a942c8f9798d053 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56215 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Timothy Day Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- libcfs/libcfs/module.c | 31 +++++++++++++++++++------------ libcfs/libcfs/tracefile.c | 4 ++++ lnet/lnet/lnet_debugfs.c | 2 ++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/libcfs/libcfs/module.c b/libcfs/libcfs/module.c index 9377771..b59e15a 100644 --- a/libcfs/libcfs/module.c +++ b/libcfs/libcfs/module.c @@ -111,6 +111,8 @@ static int proc_dobitmasks(const struct ctl_table *table, tmpstr + pos, NULL); } } else { + if (nob > USHRT_MAX) + return -E2BIG; tmpstr = memdup_user_nul(buffer, nob); if (IS_ERR(tmpstr)) return PTR_ERR(tmpstr); @@ -182,12 +184,13 @@ static int proc_fail_loc(const struct ctl_table *table, } if (write) { - char *kbuf = memdup_user_nul(buffer, *lenp); + char kbuf[sizeof(cfs_fail_loc) * 4] = { '\0' }; - if (IS_ERR(kbuf)) - return PTR_ERR(kbuf); + if (*lenp > sizeof(kbuf)) + return -E2BIG; + if (copy_from_user(kbuf, buffer, *lenp)) + return -EFAULT; rc = kstrtoul(kbuf, 0, &cfs_fail_loc); - kfree(kbuf); *ppos += *lenp; } else { char kbuf[64/3+3]; @@ -249,14 +252,16 @@ int debugfs_doint(const struct ctl_table *table, int write, } if (write) { - char *kbuf = memdup_user_nul(buffer, *lenp); int val; + char kbuf[sizeof(val) * 4] = { '\0' }; + + if (*lenp > sizeof(kbuf)) + return -E2BIG; - if (IS_ERR(kbuf)) - return PTR_ERR(kbuf); + if (copy_from_user(kbuf, buffer, *lenp)) + return -EFAULT; rc = kstrtoint(kbuf, 0, &val); - kfree(kbuf); if (!rc) { if (table->extra1 && val < *(int *)table->extra1) val = *(int *)table->extra1; @@ -292,14 +297,16 @@ static int debugfs_dou64(const struct ctl_table *table, int write, } if (write) { - char *kbuf = memdup_user_nul(buffer, *lenp); unsigned long long val; + char kbuf[sizeof(val) * 4] = { '\0' }; - if (IS_ERR(kbuf)) - return PTR_ERR(kbuf); + if (*lenp > sizeof(kbuf)) + return -E2BIG; + + if (copy_from_user(kbuf, buffer, *lenp)) + return -EFAULT; rc = kstrtoull(kbuf, 0, &val); - kfree(kbuf); if (!rc) *(u64 *)table->data = val; *ppos += *lenp; diff --git a/libcfs/libcfs/tracefile.c b/libcfs/libcfs/tracefile.c index a6dd2a0..4084da9 100644 --- a/libcfs/libcfs/tracefile.c +++ b/libcfs/libcfs/tracefile.c @@ -1019,6 +1019,8 @@ int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob) char *path; int rc; + if (usr_str_nob > PATH_MAX) + return -E2BIG; str = memdup_user_nul(usr_str, usr_str_nob); if (IS_ERR(str)) return PTR_ERR(str); @@ -1077,6 +1079,8 @@ int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob) char *str; int rc; + if (usr_str_nob > USHRT_MAX) + return -E2BIG; str = memdup_user_nul(usr_str, usr_str_nob); if (IS_ERR(str)) return PTR_ERR(str); diff --git a/lnet/lnet/lnet_debugfs.c b/lnet/lnet/lnet_debugfs.c index 9665893..5403d27 100644 --- a/lnet/lnet/lnet_debugfs.c +++ b/lnet/lnet/lnet_debugfs.c @@ -885,6 +885,8 @@ static int proc_lnet_portal_rotor(const struct ctl_table *table, return rc; } + if (nob > USHRT_MAX) + return -E2BIG; buf = memdup_user_nul(buffer, nob); if (IS_ERR(buf)) return PTR_ERR(buf); -- 1.8.3.1