syd 3.52.0

rock-solid application kernel
Documentation
//
// Syd: rock-solid application kernel
// src/kernel/prctl.rs: prctl(2) handler
//
// Copyright (c) 2023, 2024, 2025, 2026 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0

// SAFETY: This module has been liberated from unsafe code!
#![forbid(unsafe_code)]

use libseccomp::ScmpNotifResp;
use memchr::memchr;
use nix::errno::Errno;

use crate::{
    confine::is_valid_ptr, log::log_untrusted_buf, proc::proc_comm, req::UNotifyEventRequest, warn,
};

#[expect(clippy::cognitive_complexity)]
pub(crate) fn sys_prctl(request: UNotifyEventRequest) -> ScmpNotifResp {
    syscall_handler!(request, |request: UNotifyEventRequest| {
        // We only hook into the PR_SET_NAME request.
        let req = request.scmpreq;

        // Linux kernel truncates upper bits.
        #[expect(clippy::cast_possible_truncation)]
        let op = req.data.args[0] as u32;
        assert_eq!(op, libc::PR_SET_NAME as u32);

        // Check pointer against mmap_min_addr.
        let ptr = req.data.args[1];
        if !is_valid_ptr(ptr, req.data.arch) {
            return Err(Errno::EFAULT);
        }

        let sandbox = request.get_sandbox();
        if !sandbox.log_prctl() {
            return Ok(request.return_syscall(0));
        }
        drop(sandbox); // release the read-lock.

        let mut buf = [0u8; 15];
        let name = match request.read_mem(&mut buf, ptr, 15) {
            Ok(len) => {
                let nil = memchr(0, &buf[..len]).unwrap_or(len);
                &buf[..nil]
            }
            Err(errno) => return Err(errno),
        };

        // See if this is a request for change,
        // silently deny if no change was attempted.
        match proc_comm(req.pid()) {
            Ok(comm) if comm.is_equal(name) => {}
            Ok(comm) => {
                let (name, hex) = log_untrusted_buf(name);
                warn!("ctx": "change_process_name",
                    "msg": format!("attempt to change process name from `{comm}' to `{name}' prevented"),
                    "tip": "use log/verbose:0 to silence, trace/allow_unsafe_prctl:1 to allow",
                    "sys": request.syscall, "name": name, "hex": hex, "comm": comm, "pid": req.pid,
                    "req": &request);
            }
            Err(_) => {
                let (name, hex) = log_untrusted_buf(name);
                warn!("ctx": "change_process_name",
                    "msg": format!("attempt to change process name to `{name}' prevented"),
                    "tip": "use log/verbose:0 to silence, trace/allow_unsafe_prctl:1 to allow",
                    "sys": request.syscall, "name": name, "hex": hex, "pid": req.pid,
                    "req": &request);
            }
        }

        Ok(request.return_syscall(0))
    })
}