Whamcloud - gitweb
LU-18186 libcfs: avoid kmalloc order > MAX_PAGE_ORDER 15/56215/13
authorShaun Tancheff <shaun.tancheff@hpe.com>
Sat, 15 Feb 2025 11:17:46 +0000 (18:17 +0700)
committerOleg Drokin <green@whamcloud.com>
Sat, 22 Feb 2025 23:41:33 +0000 (23:41 +0000)
    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 <shaun.tancheff@hpe.com>
Change-Id: Ide49aa3870cadc43c520f29b0a942c8f9798d053
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56215
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Timothy Day <timday@amazon.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/libcfs/module.c
libcfs/libcfs/tracefile.c
lnet/lnet/lnet_debugfs.c

index 9377771..b59e15a 100644 (file)
@@ -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;
index a6dd2a0..4084da9 100644 (file)
@@ -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);
index 9665893..5403d27 100644 (file)
@@ -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);