From nobody Mon May 25 02:42:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2BA673F4DD5; Tue, 19 May 2026 12:24:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779193480; cv=none; b=XDF3aysqIwKCY0rAAB2c1LR8GVYobUFhggD7K7In0yIsQ2r4eJL3l0amj67fFEVLG31PQ9928joHsAd/OSEdk5cSD0jdC8cDqgnsj0e+stXuT90ev72ZxLfrnBWfRqTMsvMpUcA+3lxhmxqV+aeQxK4vBBFusW4jHcsmDDKoBpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779193480; c=relaxed/simple; bh=U6uqIHy8EE/i1NqW9z07GrDK43NwFSOtpRCXLlkTT/w=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=pX1m8p3jlZGDrMZR4wHG2+z9hjpE5M/1bPg6TLgl0pltbAgvcP4tloSZxW8oDAEQ3t5yRRuR/FzjqBTXhTshsRB64IDqdsbuigtML8o2xmm/zqmv9LUqLTOFw68XBxoiyi56VfGK05lQbOWsTr3mY8Zgce3o4mUiDMZxr24kD0s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LC03JEtE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LC03JEtE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 84F81C2BCB8; Tue, 19 May 2026 12:24:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1779193479; bh=U6uqIHy8EE/i1NqW9z07GrDK43NwFSOtpRCXLlkTT/w=; h=From:To:Cc:Subject:Date:From; b=LC03JEtE9gEcI9GO3u+nUrkxOlo/J8fohNMiQ1gD6BxQoj9yS9jqTP1nTPMjaa0pW parkjEr0wR7LZJ1m/Wdj0bzf5qavbL7ggPknymbczPk3dyD5gcpkIxxd18nhokPkcN n7LVA7OuX7wJnp6Pt1X8/KlFBsDrmIsfatLHlMncuHdQ6vl4l54zgru3IqnczOob4k GZVSdvX/dI62PuaES0dcOpHufMVixxZOnWG6IS7/3ecxXzBFMsG1nUu5bgyg3Oxxmy +J4PbLyvFB1lgrl112aVA/RY6fvd6B90wEknQRHrRcMfYv3rIaXd7T5HtIiXagkPUK Mn533+Z6ahxuA== From: Pratyush Yadav To: Pasha Tatashin , Mike Rapoport , Pratyush Yadav , Andrew Morton Cc: linux-kernel@vger.kernel.org, kexec@lists.infradead.org, stable@vger.kernel.org Subject: [PATCH] liveupdate: validate session type before performing operation Date: Tue, 19 May 2026 14:24:26 +0200 Message-ID: <20260519122428.2378446-1-pratyush@kernel.org> X-Mailer: git-send-email 2.54.0.563.g4f69b47b94-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Pratyush Yadav (Google)" The sessions ioctls are not applicable to all session types. PRESERVE_FD is only applicable to outgoing sessions. RETRIEVE_FD and FINISH are only valid for incoming session. Calling a incoming ioctl on an outgoing session is invalid and can cause file handlers to run into unexpected errors. For example, a user can create a (outgoing) session, preserve a memfd, and then immediately do a retrieve without doing a kexec in between. This would result in memfd's retrieve handler to run. The handlers expects to be called from a post-kexec context, and will try to do a kho_restore_vmalloc() or kho_restore_folio() to try and restore memory. KHO catches this (thanks to KHO_PAGE_MAGIC) and returns an error, but since this is considered an internal error and KHO throws out a bunch of WARN()s. Associate a type with each ioctl op and validate the type in luo_session_ioctl() before dispatching the ioctl handler to make sure the op is being called for the right session type. Fixes: 16cec0d26521 ("liveupdate: luo_session: add ioctls for file preserva= tion") Cc: stable@vger.kernel.org Signed-off-by: Pratyush Yadav (Google) --- Notes: I added LUO_IOCTL_ALL but there is no user in this patch. The type is for LIVEUPDATE_SESSION_GET_NAME which is supported for both session types. The support for GET_NAME is in next and this patch should go through fixes. =20 Alternatively, we can remove LUO_IOCTL_ALL from this patch and add it to the LIVEUPDATE_SESSION_GET_NAME patch in next. But that would need us to rebase to an rc that contains this fix. kernel/liveupdate/luo_session.c | 36 +++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_sessio= n.c index a3327a28fc1f..e84218e3cacb 100644 --- a/kernel/liveupdate/luo_session.c +++ b/kernel/liveupdate/luo_session.c @@ -295,32 +295,58 @@ union ucmd_buffer { struct liveupdate_session_retrieve_fd retrieve; }; =20 +/* Type of sessions the ioctl applies to. */ +enum luo_ioctl_type { + LUO_IOCTL_INCOMING, + LUO_IOCTL_OUTGOING, + LUO_IOCTL_ALL, +}; + struct luo_ioctl_op { unsigned int size; unsigned int min_size; unsigned int ioctl_num; + enum luo_ioctl_type type; int (*execute)(struct luo_session *session, struct luo_ucmd *ucmd); }; =20 -#define IOCTL_OP(_ioctl, _fn, _struct, _last) = \ +#define IOCTL_OP(_ioctl, _fn, _struct, _last, _type) = \ [_IOC_NR(_ioctl) - LIVEUPDATE_CMD_SESSION_BASE] =3D { \ .size =3D sizeof(_struct) + \ BUILD_BUG_ON_ZERO(sizeof(union ucmd_buffer) < \ sizeof(_struct)), \ .min_size =3D offsetofend(_struct, _last), \ .ioctl_num =3D _ioctl, \ + .type =3D _type, \ .execute =3D _fn, \ } =20 static const struct luo_ioctl_op luo_session_ioctl_ops[] =3D { IOCTL_OP(LIVEUPDATE_SESSION_FINISH, luo_session_finish, - struct liveupdate_session_finish, reserved), + struct liveupdate_session_finish, reserved, LUO_IOCTL_INCOMING), IOCTL_OP(LIVEUPDATE_SESSION_PRESERVE_FD, luo_session_preserve_fd, - struct liveupdate_session_preserve_fd, token), + struct liveupdate_session_preserve_fd, token, LUO_IOCTL_OUTGOING), IOCTL_OP(LIVEUPDATE_SESSION_RETRIEVE_FD, luo_session_retrieve_fd, - struct liveupdate_session_retrieve_fd, token), + struct liveupdate_session_retrieve_fd, token, LUO_IOCTL_INCOMING), }; =20 +static bool luo_ioctl_type_valid(struct luo_session *session, + const struct luo_ioctl_op *op) +{ + switch (op->type) { + case LUO_IOCTL_INCOMING: + /* Retrieved is only set on incoming sessions */ + return session->retrieved; + case LUO_IOCTL_OUTGOING: + return !session->retrieved; + case LUO_IOCTL_ALL: + return true; + } + + /* Catch-all. */ + return false; +} + static long luo_session_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { @@ -345,6 +371,8 @@ static long luo_session_ioctl(struct file *filep, unsig= ned int cmd, op =3D &luo_session_ioctl_ops[nr - LIVEUPDATE_CMD_SESSION_BASE]; if (op->ioctl_num !=3D cmd) return -ENOIOCTLCMD; + if (!luo_ioctl_type_valid(session, op)) + return -EINVAL; if (ucmd.user_size < op->min_size) return -EINVAL; =20 base-commit: b1378127003b61930ce30064328640503ad3ef6d --=20 2.54.0.563.g4f69b47b94-goog