From: Vandana Rungta Date: Fri, 21 Mar 2025 16:06:25 +0000 (+0000) Subject: LU-18845 obdclass: NPE in with_imp_locked_nested X-Git-Tag: 2.16.55~98 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=62276528bafd4a26885991478e577bad44901871;p=fs%2Flustre-release.git LU-18845 obdclass: NPE in with_imp_locked_nested Unable to handle kernel NULL pointer dereference at virtual address 0000000000000588 down_read+0x28/0x100 active_show+0x2c/0x90 [osp] lustre_attr_show+0x1c/0x2c [obdclass] active_show calls macro with_imp_locked with an obd_device, which in turn gets a lock on u.cli.cl_sem in obd_device. The exception is at offset 0x588, and u.cli.cl_sem is at 0x588 in struct obd_device, which confirms that a NULL obd was being used. This fix adds checks for NULL obd to active_show. Signed-off-by: Vandana Rungta Change-Id: Ia0ff9e7a07f40bb7dd9c0d4cc0ecc38ea8d61d0b Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58499 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin Reviewed-by: Neil Brown Reviewed-by: James Simmons Reviewed-by: Timothy Day --- diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 54fc627..1821c2f 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -699,6 +699,36 @@ extern int lprocfs_seq_release(struct inode *i, struct file *f); * to get out of the statement. */ +/* + * The macro uses a for loop that executes a block of code maximum once. + * It allows for local variable declarations. + * + * Initialization: Lock Acquisition and Import Retrieval: + * -------------- + * for (down_read_nested(&(__obd)->u.cli.cl_sem, __nest), + * __imp = (__obd)->u.cli.cl_import, + * __rc = __imp ? 0 : -ENODEV; + * It acquires a read lock, + * retrieves the import pointer and stores it in __imp, + * sets the return code __rc + * to 0 (success) if __imp is not NULL, or + * to _ENODEV (failure) if __imp is NULL + * + * Condition: Conditional Lock Release: + * --------- + * __imp ? 1 : (up_read(&(__obd)->u.cli.cl_sem), 0); + * + * If __imp is not NULL, it evaluates to 1, and nothing happens. + * This means the lock is kept as long as a valid import was obtained. + * If __imp is NULL, then it releases the read lock and evaluates to 0. + * + * Update: Nulling the Import Pointer + * ------ + * __imp = NULL) + * + * sets __imp to NULL. This will break out of the for loop, releasing the + * semaphore in the condition. + */ #define with_imp_locked_nested(__obd, __imp, __rc, __nest) \ for (down_read_nested(&(__obd)->u.cli.cl_sem, __nest), \ __imp = (__obd)->u.cli.cl_import, \ diff --git a/lustre/osp/lproc_osp.c b/lustre/osp/lproc_osp.c index 6b03245..4e7630a 100644 --- a/lustre/osp/lproc_osp.c +++ b/lustre/osp/lproc_osp.c @@ -37,6 +37,9 @@ static ssize_t active_show(struct kobject *kobj, struct attribute *attr, struct obd_import *imp; int rc; + if (!obd) + return -ENOENT; + with_imp_locked(obd, imp, rc) rc = sprintf(buf, "%d\n", !imp->imp_deactive); return rc;