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

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 {
    // Note, we only hook into the PR_SET_NAME request.
    let req = request.scmpreq;

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

    let sandbox = request.get_sandbox();
    if !sandbox.log_prctl() {
        return 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(err) => return request.fail_syscall(err),
    };

    // 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);
        }
    }

    request.return_syscall(0)
}
