ipc: limit next_id allocation to the valid ID range

JIRA: https://redhat.atlassian.net/browse/RHEL-188213
CVE: CVE-2026-52923

commit fa0b9b2b7ae3539908d69c2b9ac0d144d9bc5139
Author: Linpu Yu <linpu5433@gmail.com>
Date:   Sun May 10 13:43:30 2026 +0800

    ipc: limit next_id allocation to the valid ID range

    The checkpoint/restore sysctl path can request the next SysV IPC id
    through ids->next_id.  ipc_idr_alloc() currently forwards that request to
    idr_alloc() with an open-ended upper bound.

    If the valid tail of the SysV IPC id space is full, the allocation can
    spill beyond ipc_mni.  The returned SysV IPC id still uses the normal
    index encoding, so later lookup and removal can target the wrong slot.
    This leaves the real IDR entry behind and breaks the IDR state for the
    object.

    The bug is in ipc_idr_alloc() in the checkpoint/restore path.

    1. ids->next_id is passed to:

           idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id), 0, ...)

    2. The zero upper bound makes the allocation effectively open-ended.
       Once the valid SysV IPC tail is occupied, idr_alloc() can spill past
       ipc_mni and allocate an entry beyond the valid IPC id range.

    3. The new object id is still encoded with the narrower SysV IPC index
       width:

           new->id = (new->seq << ipcmni_seq_shift()) + idx

    4. Later removal goes through ipc_rmid(), which uses:

           ipcid_to_idx(ipcp->id)

       That truncates the real IDR index. An object actually stored at a
       high index can then be removed as if it lived at a low in-range
       index.

    5. For shared memory, shm_destroy() frees the current object anyway, but
       the real high IDR slot is left behind as a dangling pointer.

    6. A subsequent walk of /proc/sysvipc/shm reaches the stale IDR entry
       and dereferences freed memory.

    Prevent this by bounding the requested allocation to ipc_mni so the
    checkpoint/restore path fails once the valid range is exhausted.

    Link: https://lore.kernel.org/cover.1778336914.git.linpu5433@gmail.com
    Link: https://lore.kernel.org/2eebe949bfa7d1f6e13b5be6a92c64c850ce9d45.1778336914.git.linpu5433@gmail.com
    Fixes: 03f5956680 ("ipc: add sysctl to specify desired next object id")
    Signed-off-by: Linpu Yu <linpu5433@gmail.com>
    Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
    Reported-by: Yuan Tan <yuantan098@gmail.com>
    Reported-by: Yifan Wu <yifanwucs@gmail.com>
    Reported-by: Juefei Pu <tomapufckgml@gmail.com>
    Reported-by: Xin Liu <bird@lzu.edu.cn>
    Cc: Kees Cook <kees@kernel.org>
    Cc: Stanislav Kinsbursky <skinsbursky@parallels.com>
    Cc: Davidlohr Bueso <dave@stgolabs.net>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Signed-off-by: Rafael Aquini <raquini@redhat.com>
This commit is contained in:
Rafael Aquini
2026-06-29 11:43:31 -04:00
parent 8d084145fd
commit 65b927440a
+1 -1
View File
@@ -253,7 +253,7 @@ static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
} else {
new->seq = ipcid_to_seqx(next_id);
idx = idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id),
0, GFP_NOWAIT);
ipc_mni, GFP_NOWAIT);
}
if (idx >= 0)
new->id = (new->seq << ipcmni_seq_shift()) + idx;